xref: /petsc/src/ksp/pc/impls/telescope/telescope.c (revision 392968a1be245f4b38d3fd4e2696cb729179339e)
11e07b27eSBarry Smith 
2120bdd93SDave May #include <petsc/private/matimpl.h>
36fc41876SBarry Smith #include <petsc/private/pcimpl.h>
41e07b27eSBarry Smith #include <petscksp.h> /*I "petscksp.h" I*/
51e07b27eSBarry Smith #include <petscdm.h> /*I "petscdm.h" I*/
6575a0592SBarry Smith #include "../src/ksp/pc/impls/telescope/telescope.h"
71e07b27eSBarry Smith 
81e07b27eSBarry Smith /*
91e07b27eSBarry Smith  PCTelescopeSetUp_default()
101e07b27eSBarry Smith  PCTelescopeMatCreate_default()
111e07b27eSBarry Smith 
121e07b27eSBarry Smith  default
131e07b27eSBarry Smith 
141e07b27eSBarry Smith  // scatter in
151e07b27eSBarry Smith  x(comm) -> xtmp(comm)
161e07b27eSBarry Smith 
171e07b27eSBarry Smith  xred(subcomm) <- xtmp
181e07b27eSBarry Smith  yred(subcomm)
191e07b27eSBarry Smith 
201e07b27eSBarry Smith  yred(subcomm) --> xtmp
211e07b27eSBarry Smith 
221e07b27eSBarry Smith  // scatter out
231e07b27eSBarry Smith  xtmp(comm) -> y(comm)
241e07b27eSBarry Smith */
251e07b27eSBarry Smith 
261e07b27eSBarry Smith PetscBool isActiveRank(PetscSubcomm scomm)
271e07b27eSBarry Smith {
281e07b27eSBarry Smith   if (scomm->color == 0) { return PETSC_TRUE; }
291e07b27eSBarry Smith   else { return PETSC_FALSE; }
301e07b27eSBarry Smith }
311e07b27eSBarry Smith 
321e07b27eSBarry Smith #undef __FUNCT__
331e07b27eSBarry Smith #define __FUNCT__ "private_PCTelescopeGetSubDM"
341e07b27eSBarry Smith DM private_PCTelescopeGetSubDM(PC_Telescope sred)
351e07b27eSBarry Smith {
36c6a0d831SBarry Smith   DM subdm = NULL;
371e07b27eSBarry Smith 
381e07b27eSBarry Smith   if (!isActiveRank(sred->psubcomm)) { subdm = NULL; }
391e07b27eSBarry Smith   else {
401e07b27eSBarry Smith     switch (sred->sr_type) {
411e07b27eSBarry Smith     case TELESCOPE_DEFAULT: subdm = NULL;
421e07b27eSBarry Smith       break;
431e07b27eSBarry Smith     case TELESCOPE_DMDA:    subdm = ((PC_Telescope_DMDACtx*)sred->dm_ctx)->dmrepart;
441e07b27eSBarry Smith       break;
451e07b27eSBarry Smith     case TELESCOPE_DMPLEX:  subdm = NULL;
461e07b27eSBarry Smith       break;
471e07b27eSBarry Smith     }
481e07b27eSBarry Smith   }
491e07b27eSBarry Smith   return(subdm);
501e07b27eSBarry Smith }
511e07b27eSBarry Smith 
521e07b27eSBarry Smith #undef __FUNCT__
531e07b27eSBarry Smith #define __FUNCT__ "PCTelescopeSetUp_default"
541e07b27eSBarry Smith PetscErrorCode PCTelescopeSetUp_default(PC pc,PC_Telescope sred)
551e07b27eSBarry Smith {
561e07b27eSBarry Smith   PetscErrorCode ierr;
571e07b27eSBarry Smith   PetscInt       m,M,bs,st,ed;
581e07b27eSBarry Smith   Vec            x,xred,yred,xtmp;
591e07b27eSBarry Smith   Mat            B;
601e07b27eSBarry Smith   MPI_Comm       comm,subcomm;
611e07b27eSBarry Smith   VecScatter     scatter;
621e07b27eSBarry Smith   IS             isin;
631e07b27eSBarry Smith 
641e07b27eSBarry Smith   PetscFunctionBegin;
651e07b27eSBarry Smith   ierr = PetscInfo(pc,"PCTelescope: setup (default)\n");CHKERRQ(ierr);
661e07b27eSBarry Smith   comm = PetscSubcommParent(sred->psubcomm);
671e07b27eSBarry Smith   subcomm = PetscSubcommChild(sred->psubcomm);
681e07b27eSBarry Smith 
691e07b27eSBarry Smith   ierr = PCGetOperators(pc,NULL,&B);CHKERRQ(ierr);
701e07b27eSBarry Smith   ierr = MatGetSize(B,&M,NULL);CHKERRQ(ierr);
711e07b27eSBarry Smith   ierr = MatGetBlockSize(B,&bs);CHKERRQ(ierr);
721e07b27eSBarry Smith   ierr = MatCreateVecs(B,&x,NULL);CHKERRQ(ierr);
731e07b27eSBarry Smith 
741e07b27eSBarry Smith   xred = NULL;
753ac26c5eSBarry Smith   m    = 0;
761e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
771e07b27eSBarry Smith     ierr = VecCreate(subcomm,&xred);CHKERRQ(ierr);
781e07b27eSBarry Smith     ierr = VecSetSizes(xred,PETSC_DECIDE,M);CHKERRQ(ierr);
791e07b27eSBarry Smith     ierr = VecSetBlockSize(xred,bs);CHKERRQ(ierr);
801e07b27eSBarry Smith     ierr = VecSetFromOptions(xred);CHKERRQ(ierr);
81ca43db0aSBarry Smith     ierr = VecGetLocalSize(xred,&m);CHKERRQ(ierr);
821e07b27eSBarry Smith   }
831e07b27eSBarry Smith 
841e07b27eSBarry Smith   yred = NULL;
851e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
861e07b27eSBarry Smith     ierr = VecDuplicate(xred,&yred);CHKERRQ(ierr);
871e07b27eSBarry Smith   }
881e07b27eSBarry Smith 
891e07b27eSBarry Smith   ierr = VecCreate(comm,&xtmp);CHKERRQ(ierr);
901e07b27eSBarry Smith   ierr = VecSetSizes(xtmp,m,PETSC_DECIDE);CHKERRQ(ierr);
911e07b27eSBarry Smith   ierr = VecSetBlockSize(xtmp,bs);CHKERRQ(ierr);
921e07b27eSBarry Smith   ierr = VecSetType(xtmp,((PetscObject)x)->type_name);CHKERRQ(ierr);
931e07b27eSBarry Smith 
941e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
951e07b27eSBarry Smith     ierr = VecGetOwnershipRange(xred,&st,&ed);CHKERRQ(ierr);
961e07b27eSBarry Smith     ierr = ISCreateStride(comm,(ed-st),st,1,&isin);CHKERRQ(ierr);
971e07b27eSBarry Smith   } else {
981e07b27eSBarry Smith     ierr = VecGetOwnershipRange(x,&st,&ed);CHKERRQ(ierr);
993ac26c5eSBarry Smith     ierr = ISCreateStride(comm,0,st,1,&isin);CHKERRQ(ierr);
1001e07b27eSBarry Smith   }
1011e07b27eSBarry Smith   ierr = ISSetBlockSize(isin,bs);CHKERRQ(ierr);
1021e07b27eSBarry Smith 
1031e07b27eSBarry Smith   ierr = VecScatterCreate(x,isin,xtmp,NULL,&scatter);CHKERRQ(ierr);
1041e07b27eSBarry Smith 
1051e07b27eSBarry Smith   sred->isin    = isin;
1061e07b27eSBarry Smith   sred->scatter = scatter;
1071e07b27eSBarry Smith   sred->xred    = xred;
1081e07b27eSBarry Smith   sred->yred    = yred;
1091e07b27eSBarry Smith   sred->xtmp    = xtmp;
1101e07b27eSBarry Smith   ierr = VecDestroy(&x);CHKERRQ(ierr);
1111e07b27eSBarry Smith   PetscFunctionReturn(0);
1121e07b27eSBarry Smith }
1131e07b27eSBarry Smith 
1141e07b27eSBarry Smith #undef __FUNCT__
1151e07b27eSBarry Smith #define __FUNCT__ "PCTelescopeMatCreate_default"
1161e07b27eSBarry Smith PetscErrorCode PCTelescopeMatCreate_default(PC pc,PC_Telescope sred,MatReuse reuse,Mat *A)
1171e07b27eSBarry Smith {
1181e07b27eSBarry Smith   PetscErrorCode ierr;
1191e07b27eSBarry Smith   MPI_Comm       comm,subcomm;
1201e07b27eSBarry Smith   Mat            Bred,B;
1211e07b27eSBarry Smith   PetscInt       nr,nc;
1221e07b27eSBarry Smith   IS             isrow,iscol;
1231e07b27eSBarry Smith   Mat            Blocal,*_Blocal;
1241e07b27eSBarry Smith 
1251e07b27eSBarry Smith   PetscFunctionBegin;
1261e07b27eSBarry Smith   ierr = PetscInfo(pc,"PCTelescope: updating the redundant preconditioned operator (default)\n");CHKERRQ(ierr);
1271e07b27eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
1281e07b27eSBarry Smith   subcomm = PetscSubcommChild(sred->psubcomm);
1291e07b27eSBarry Smith   ierr = PCGetOperators(pc,NULL,&B);CHKERRQ(ierr);
1301e07b27eSBarry Smith   ierr = MatGetSize(B,&nr,&nc);CHKERRQ(ierr);
1311e07b27eSBarry Smith   isrow = sred->isin;
1321e07b27eSBarry Smith   ierr = ISCreateStride(comm,nc,0,1,&iscol);CHKERRQ(ierr);
1331e07b27eSBarry Smith   ierr = MatGetSubMatrices(B,1,&isrow,&iscol,MAT_INITIAL_MATRIX,&_Blocal);CHKERRQ(ierr);
1341e07b27eSBarry Smith   Blocal = *_Blocal;
1351e07b27eSBarry Smith   ierr = PetscFree(_Blocal);CHKERRQ(ierr);
1361e07b27eSBarry Smith   Bred = NULL;
1371e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
1381e07b27eSBarry Smith     PetscInt mm;
1391e07b27eSBarry Smith 
1401e07b27eSBarry Smith     if (reuse != MAT_INITIAL_MATRIX) { Bred = *A; }
1411e07b27eSBarry Smith 
1421e07b27eSBarry Smith     ierr = MatGetSize(Blocal,&mm,NULL);CHKERRQ(ierr);
1431e07b27eSBarry Smith     ierr = MatCreateMPIMatConcatenateSeqMat(subcomm,Blocal,mm,reuse,&Bred);CHKERRQ(ierr);
1441e07b27eSBarry Smith   }
1451e07b27eSBarry Smith   *A = Bred;
1461e07b27eSBarry Smith   ierr = ISDestroy(&iscol);CHKERRQ(ierr);
1471e07b27eSBarry Smith   ierr = MatDestroy(&Blocal);CHKERRQ(ierr);
1481e07b27eSBarry Smith   PetscFunctionReturn(0);
1491e07b27eSBarry Smith }
1501e07b27eSBarry Smith 
1511e07b27eSBarry Smith #undef __FUNCT__
152*392968a1SPatrick Sanan #define __FUNCT__ "PCTelescopeSubNullSpaceCreate_Telescope"
153*392968a1SPatrick Sanan static PetscErrorCode PCTelescopeSubNullSpaceCreate_Telescope(PC pc,PC_Telescope sred,MatNullSpace nullspace,MatNullSpace *sub_nullspace)
1541e07b27eSBarry Smith {
1551e07b27eSBarry Smith   PetscErrorCode   ierr;
1561e07b27eSBarry Smith   PetscBool        has_const;
1571e07b27eSBarry Smith   const Vec        *vecs;
158c41e779fSDave May   Vec              *sub_vecs = NULL;
159*392968a1SPatrick Sanan   PetscInt         i,k,n = 0;
1601e07b27eSBarry Smith   MPI_Comm         subcomm;
1611e07b27eSBarry Smith 
1621e07b27eSBarry Smith   PetscFunctionBegin;
1631e07b27eSBarry Smith   subcomm = PetscSubcommChild(sred->psubcomm);
1641e07b27eSBarry Smith   ierr = MatNullSpaceGetVecs(nullspace,&has_const,&n,&vecs);CHKERRQ(ierr);
1651e07b27eSBarry Smith 
1661e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
167e3acf2f7SBarry Smith     if (n) {
168e3acf2f7SBarry Smith       ierr = VecDuplicateVecs(sred->xred,n,&sub_vecs);CHKERRQ(ierr);
1691e07b27eSBarry Smith     }
1701e07b27eSBarry Smith   }
1711e07b27eSBarry Smith 
1721e07b27eSBarry Smith   /* copy entries */
1731e07b27eSBarry Smith   for (k=0; k<n; k++) {
1741e07b27eSBarry Smith     const PetscScalar *x_array;
1751e07b27eSBarry Smith     PetscScalar       *LA_sub_vec;
17613c30530SDave May     PetscInt          st,ed;
1771e07b27eSBarry Smith 
1781e07b27eSBarry Smith     /* pull in vector x->xtmp */
1791e07b27eSBarry Smith     ierr = VecScatterBegin(sred->scatter,vecs[k],sred->xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1801e07b27eSBarry Smith     ierr = VecScatterEnd(sred->scatter,vecs[k],sred->xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18147856c66SBarry Smith     if (sub_vecs) {
182a04a6428SPatrick Sanan       /* copy vector entries into xred */
1831e07b27eSBarry Smith       ierr = VecGetArrayRead(sred->xtmp,&x_array);CHKERRQ(ierr);
184ea2b237eSDave May       if (sub_vecs[k]) {
1851e07b27eSBarry Smith         ierr = VecGetOwnershipRange(sub_vecs[k],&st,&ed);CHKERRQ(ierr);
1861e07b27eSBarry Smith         ierr = VecGetArray(sub_vecs[k],&LA_sub_vec);CHKERRQ(ierr);
1871e07b27eSBarry Smith         for (i=0; i<ed-st; i++) {
1881e07b27eSBarry Smith           LA_sub_vec[i] = x_array[i];
1891e07b27eSBarry Smith         }
1901e07b27eSBarry Smith         ierr = VecRestoreArray(sub_vecs[k],&LA_sub_vec);CHKERRQ(ierr);
1911e07b27eSBarry Smith       }
1921e07b27eSBarry Smith       ierr = VecRestoreArrayRead(sred->xtmp,&x_array);CHKERRQ(ierr);
1931e07b27eSBarry Smith     }
19447856c66SBarry Smith   }
1951e07b27eSBarry Smith 
1961e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
197d8b9d5b7SPatrick Sanan     /* create new (near) nullspace for redundant object */
198*392968a1SPatrick Sanan     ierr = MatNullSpaceCreate(subcomm,has_const,n,sub_vecs,sub_nullspace);CHKERRQ(ierr);
199*392968a1SPatrick Sanan     ierr = VecDestroyVecs(n,&sub_vecs);CHKERRQ(ierr);
200d8b9d5b7SPatrick Sanan     if (nullspace->remove) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Propagation of custom remove callbacks not supported when propagating (near) nullspaces with PCTelescope");
201d8b9d5b7SPatrick Sanan     if (nullspace->rmctx) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Propagation of custom remove callback context not supported when propagating (near) nullspaces with PCTelescope");
202d8b9d5b7SPatrick Sanan   }
203*392968a1SPatrick Sanan   PetscFunctionReturn(0);
204*392968a1SPatrick Sanan }
205*392968a1SPatrick Sanan 
206*392968a1SPatrick Sanan #undef __FUNCT__
207*392968a1SPatrick Sanan #define __FUNCT__ "PCTelescopeMatNullSpaceCreate_default"
208*392968a1SPatrick Sanan static PetscErrorCode PCTelescopeMatNullSpaceCreate_default(PC pc,PC_Telescope sred,Mat sub_mat)
209*392968a1SPatrick Sanan {
210*392968a1SPatrick Sanan   PetscErrorCode   ierr;
211*392968a1SPatrick Sanan   Mat              B;
212*392968a1SPatrick Sanan 
213*392968a1SPatrick Sanan   PetscFunctionBegin;
214*392968a1SPatrick Sanan   ierr = PCGetOperators(pc,NULL,&B);CHKERRQ(ierr);
215*392968a1SPatrick Sanan 
216*392968a1SPatrick Sanan   /* Propagate the nullspace if it exists */
217*392968a1SPatrick Sanan   {
218*392968a1SPatrick Sanan     MatNullSpace nullspace,sub_nullspace;
219*392968a1SPatrick Sanan     ierr = MatGetNullSpace(B,&nullspace);CHKERRQ(ierr);
220*392968a1SPatrick Sanan     if (nullspace) {
221*392968a1SPatrick Sanan       ierr = PetscInfo(pc,"PCTelescope: generating nullspace (default)\n");CHKERRQ(ierr);
222*392968a1SPatrick Sanan       ierr = PCTelescopeSubNullSpaceCreate_Telescope(pc,sred,nullspace,&sub_nullspace);CHKERRQ(ierr);
223*392968a1SPatrick Sanan       if (isActiveRank(sred->psubcomm)) {
224*392968a1SPatrick Sanan         ierr = MatSetNullSpace(sub_mat,sub_nullspace);CHKERRQ(ierr);
22541ff1ee9SPatrick Sanan         ierr = MatNullSpaceDestroy(&sub_nullspace);CHKERRQ(ierr);
2261e07b27eSBarry Smith       }
227*392968a1SPatrick Sanan     }
228*392968a1SPatrick Sanan   }
229*392968a1SPatrick Sanan 
230*392968a1SPatrick Sanan   /* Propagate the near nullspace if it exists */
231*392968a1SPatrick Sanan   {
232*392968a1SPatrick Sanan     MatNullSpace nearnullspace,sub_nearnullspace;
233*392968a1SPatrick Sanan     ierr = MatGetNearNullSpace(B,&nearnullspace);CHKERRQ(ierr);
234*392968a1SPatrick Sanan     if (nearnullspace) {
235*392968a1SPatrick Sanan       ierr = PetscInfo(pc,"PCTelescope: generating near nullspace (default)\n");CHKERRQ(ierr);
236*392968a1SPatrick Sanan       ierr = PCTelescopeSubNullSpaceCreate_Telescope(pc,sred,nearnullspace,&sub_nearnullspace);CHKERRQ(ierr);
237*392968a1SPatrick Sanan       if (isActiveRank(sred->psubcomm)) {
238*392968a1SPatrick Sanan         ierr = MatSetNearNullSpace(sub_mat,sub_nearnullspace);CHKERRQ(ierr);
239*392968a1SPatrick Sanan         ierr = MatNullSpaceDestroy(&sub_nearnullspace);CHKERRQ(ierr);
240*392968a1SPatrick Sanan       }
241*392968a1SPatrick Sanan     }
242*392968a1SPatrick Sanan   }
2431e07b27eSBarry Smith   PetscFunctionReturn(0);
2441e07b27eSBarry Smith }
2451e07b27eSBarry Smith 
2461e07b27eSBarry Smith #undef __FUNCT__
2471e07b27eSBarry Smith #define __FUNCT__ "PCView_Telescope"
2481e07b27eSBarry Smith static PetscErrorCode PCView_Telescope(PC pc,PetscViewer viewer)
2491e07b27eSBarry Smith {
2501e07b27eSBarry Smith   PC_Telescope     sred = (PC_Telescope)pc->data;
2511e07b27eSBarry Smith   PetscErrorCode   ierr;
2521e07b27eSBarry Smith   PetscBool        iascii,isstring;
2531e07b27eSBarry Smith   PetscViewer      subviewer;
2541e07b27eSBarry Smith 
2551e07b27eSBarry Smith   PetscFunctionBegin;
2561e07b27eSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
2571e07b27eSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr);
2581e07b27eSBarry Smith   if (iascii) {
2591e07b27eSBarry Smith     if (!sred->psubcomm) {
2601e07b27eSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Telescope: preconditioner not yet setup\n");CHKERRQ(ierr);
2611e07b27eSBarry Smith     } else {
2621e07b27eSBarry Smith       MPI_Comm    comm,subcomm;
2631e07b27eSBarry Smith       PetscMPIInt comm_size,subcomm_size;
2641e07b27eSBarry Smith       DM          dm,subdm;
2651e07b27eSBarry Smith 
2661e07b27eSBarry Smith       ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
2671e07b27eSBarry Smith       subdm = private_PCTelescopeGetSubDM(sred);
2681e07b27eSBarry Smith       comm = PetscSubcommParent(sred->psubcomm);
2691e07b27eSBarry Smith       subcomm = PetscSubcommChild(sred->psubcomm);
2701e07b27eSBarry Smith       ierr = MPI_Comm_size(comm,&comm_size);CHKERRQ(ierr);
2711e07b27eSBarry Smith       ierr = MPI_Comm_size(subcomm,&subcomm_size);CHKERRQ(ierr);
2721e07b27eSBarry Smith 
2731e07b27eSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Telescope: parent comm size reduction factor = %D\n",sred->redfactor);CHKERRQ(ierr);
2741e07b27eSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Telescope: comm_size = %d , subcomm_size = %d\n",(int)comm_size,(int)subcomm_size);CHKERRQ(ierr);
27548a10b22SPatrick Sanan       switch (sred->subcommtype) {
27648a10b22SPatrick Sanan         case PETSC_SUBCOMM_INTERLACED :
27748a10b22SPatrick Sanan           ierr = PetscViewerASCIIPrintf(viewer,"  Telescope: subcomm type: interlaced\n",sred->subcommtype);CHKERRQ(ierr);
27848a10b22SPatrick Sanan           break;
27948a10b22SPatrick Sanan         case PETSC_SUBCOMM_CONTIGUOUS :
28048a10b22SPatrick Sanan           ierr = PetscViewerASCIIPrintf(viewer,"  Telescope: subcomm type: contiguous\n",sred->subcommtype);CHKERRQ(ierr);
28148a10b22SPatrick Sanan           break;
28248a10b22SPatrick Sanan         default :
28348a10b22SPatrick Sanan           SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"General subcomm type not supported by PCTelescope");
28448a10b22SPatrick Sanan       }
2851e07b27eSBarry Smith       ierr = PetscViewerGetSubViewer(viewer,subcomm,&subviewer);CHKERRQ(ierr);
2861e07b27eSBarry Smith       if (isActiveRank(sred->psubcomm)) {
2871e07b27eSBarry Smith         ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr);
2881e07b27eSBarry Smith 
2891e07b27eSBarry Smith         if (dm && sred->ignore_dm) {
2901e07b27eSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: ignoring DM\n");CHKERRQ(ierr);
2911e07b27eSBarry Smith         }
2927c5279cbSDave May         if (sred->ignore_kspcomputeoperators) {
2937c5279cbSDave May           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: ignoring KSPComputeOperators\n");CHKERRQ(ierr);
2947c5279cbSDave May         }
2951e07b27eSBarry Smith         switch (sred->sr_type) {
2961e07b27eSBarry Smith         case TELESCOPE_DEFAULT:
2971e07b27eSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: using default setup\n");CHKERRQ(ierr);
2981e07b27eSBarry Smith           break;
2991e07b27eSBarry Smith         case TELESCOPE_DMDA:
3001e07b27eSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: DMDA detected\n");CHKERRQ(ierr);
3011e07b27eSBarry Smith           ierr = DMView_DMDAShort(subdm,subviewer);CHKERRQ(ierr);
3021e07b27eSBarry Smith           break;
3031e07b27eSBarry Smith         case TELESCOPE_DMPLEX:
3041e07b27eSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: DMPLEX detected\n");CHKERRQ(ierr);
3051e07b27eSBarry Smith           break;
3061e07b27eSBarry Smith         }
3071e07b27eSBarry Smith 
3081e07b27eSBarry Smith         ierr = KSPView(sred->ksp,subviewer);CHKERRQ(ierr);
3091e07b27eSBarry Smith         ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr);
3101e07b27eSBarry Smith       }
3111e07b27eSBarry Smith       ierr = PetscViewerRestoreSubViewer(viewer,subcomm,&subviewer);CHKERRQ(ierr);
3121e07b27eSBarry Smith     }
3131e07b27eSBarry Smith   }
3141e07b27eSBarry Smith   PetscFunctionReturn(0);
3151e07b27eSBarry Smith }
3161e07b27eSBarry Smith 
3171e07b27eSBarry Smith #undef __FUNCT__
3181e07b27eSBarry Smith #define __FUNCT__ "PCSetUp_Telescope"
3191e07b27eSBarry Smith static PetscErrorCode PCSetUp_Telescope(PC pc)
3201e07b27eSBarry Smith {
3211e07b27eSBarry Smith   PC_Telescope      sred = (PC_Telescope)pc->data;
3221e07b27eSBarry Smith   PetscErrorCode    ierr;
323bd49479cSSatish Balay   MPI_Comm          comm,subcomm=0;
3241e07b27eSBarry Smith   PCTelescopeType   sr_type;
3251e07b27eSBarry Smith 
3261e07b27eSBarry Smith   PetscFunctionBegin;
3271e07b27eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
3281e07b27eSBarry Smith 
3291e07b27eSBarry Smith   /* subcomm definition */
3301e07b27eSBarry Smith   if (!pc->setupcalled) {
3311e07b27eSBarry Smith     if (!sred->psubcomm) {
3321e07b27eSBarry Smith       ierr = PetscSubcommCreate(comm,&sred->psubcomm);CHKERRQ(ierr);
3331e07b27eSBarry Smith       ierr = PetscSubcommSetNumber(sred->psubcomm,sred->redfactor);CHKERRQ(ierr);
33448a10b22SPatrick Sanan       ierr = PetscSubcommSetType(sred->psubcomm,sred->subcommtype);CHKERRQ(ierr);
3351e07b27eSBarry Smith       ierr = PetscLogObjectMemory((PetscObject)pc,sizeof(PetscSubcomm));CHKERRQ(ierr);
3361e07b27eSBarry Smith     }
3371e07b27eSBarry Smith   }
3380f6f40a7SSatish Balay   subcomm = PetscSubcommChild(sred->psubcomm);
3391e07b27eSBarry Smith 
3401e07b27eSBarry Smith   /* internal KSP */
3411e07b27eSBarry Smith   if (!pc->setupcalled) {
3421e07b27eSBarry Smith     const char *prefix;
3431e07b27eSBarry Smith 
3441e07b27eSBarry Smith     if (isActiveRank(sred->psubcomm)) {
3451e07b27eSBarry Smith       ierr = KSPCreate(subcomm,&sred->ksp);CHKERRQ(ierr);
3461e07b27eSBarry Smith       ierr = KSPSetErrorIfNotConverged(sred->ksp,pc->erroriffailure);CHKERRQ(ierr);
3471e07b27eSBarry Smith       ierr = PetscObjectIncrementTabLevel((PetscObject)sred->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
3481e07b27eSBarry Smith       ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)sred->ksp);CHKERRQ(ierr);
3491e07b27eSBarry Smith       ierr = KSPSetType(sred->ksp,KSPPREONLY);CHKERRQ(ierr);
3501e07b27eSBarry Smith       ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
3511e07b27eSBarry Smith       ierr = KSPSetOptionsPrefix(sred->ksp,prefix);CHKERRQ(ierr);
3521e07b27eSBarry Smith       ierr = KSPAppendOptionsPrefix(sred->ksp,"telescope_");CHKERRQ(ierr);
3531e07b27eSBarry Smith     }
3541e07b27eSBarry Smith   }
3551e07b27eSBarry Smith   /* Determine type of setup/update */
3561e07b27eSBarry Smith   if (!pc->setupcalled) {
3571e07b27eSBarry Smith     PetscBool has_dm,same;
3581e07b27eSBarry Smith     DM        dm;
3591e07b27eSBarry Smith 
3601e07b27eSBarry Smith     sr_type = TELESCOPE_DEFAULT;
3611e07b27eSBarry Smith     has_dm = PETSC_FALSE;
3621e07b27eSBarry Smith     ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
3631e07b27eSBarry Smith     if (dm) { has_dm = PETSC_TRUE; }
3641e07b27eSBarry Smith     if (has_dm) {
3651e07b27eSBarry Smith       /* check for dmda */
3661e07b27eSBarry Smith       ierr = PetscObjectTypeCompare((PetscObject)dm,DMDA,&same);CHKERRQ(ierr);
3671e07b27eSBarry Smith       if (same) {
3681e07b27eSBarry Smith         ierr = PetscInfo(pc,"PCTelescope: found DMDA\n");CHKERRQ(ierr);
3691e07b27eSBarry Smith         sr_type = TELESCOPE_DMDA;
3701e07b27eSBarry Smith       }
3711e07b27eSBarry Smith       /* check for dmplex */
3721e07b27eSBarry Smith       ierr = PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&same);CHKERRQ(ierr);
3731e07b27eSBarry Smith       if (same) {
3741e07b27eSBarry Smith         PetscInfo(pc,"PCTelescope: found DMPLEX\n");
3751e07b27eSBarry Smith         sr_type = TELESCOPE_DMPLEX;
3761e07b27eSBarry Smith       }
3771e07b27eSBarry Smith     }
3781e07b27eSBarry Smith 
3791e07b27eSBarry Smith     if (sred->ignore_dm) {
3801e07b27eSBarry Smith       PetscInfo(pc,"PCTelescope: ignore DM\n");
3811e07b27eSBarry Smith       sr_type = TELESCOPE_DEFAULT;
3821e07b27eSBarry Smith     }
3831e07b27eSBarry Smith     sred->sr_type = sr_type;
3841e07b27eSBarry Smith   } else {
3851e07b27eSBarry Smith     sr_type = sred->sr_type;
3861e07b27eSBarry Smith   }
3871e07b27eSBarry Smith 
388d8b9d5b7SPatrick Sanan   /* set function pointers for repartition setup, matrix creation/update, matrix (near) nullspace, and reset functionality */
3891e07b27eSBarry Smith   switch (sr_type) {
3901e07b27eSBarry Smith   case TELESCOPE_DEFAULT:
3911e07b27eSBarry Smith     sred->pctelescope_setup_type              = PCTelescopeSetUp_default;
3921e07b27eSBarry Smith     sred->pctelescope_matcreate_type          = PCTelescopeMatCreate_default;
3931e07b27eSBarry Smith     sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_default;
3941e07b27eSBarry Smith     sred->pctelescope_reset_type              = NULL;
3951e07b27eSBarry Smith     break;
3961e07b27eSBarry Smith   case TELESCOPE_DMDA:
3971e07b27eSBarry Smith     pc->ops->apply                            = PCApply_Telescope_dmda;
398f650675bSDave May     pc->ops->applyrichardson                  = PCApplyRichardson_Telescope_dmda;
3991e07b27eSBarry Smith     sred->pctelescope_setup_type              = PCTelescopeSetUp_dmda;
4001e07b27eSBarry Smith     sred->pctelescope_matcreate_type          = PCTelescopeMatCreate_dmda;
4011e07b27eSBarry Smith     sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_dmda;
4021e07b27eSBarry Smith     sred->pctelescope_reset_type              = PCReset_Telescope_dmda;
4031e07b27eSBarry Smith     break;
404d8b9d5b7SPatrick Sanan   case TELESCOPE_DMPLEX: SETERRQ(comm,PETSC_ERR_SUP,"Support for DMPLEX is currently not available");
4051e07b27eSBarry Smith     break;
406a04a6428SPatrick Sanan   default: SETERRQ(comm,PETSC_ERR_SUP,"Only support for repartitioning DMDA is provided");
4071e07b27eSBarry Smith     break;
4081e07b27eSBarry Smith   }
4091e07b27eSBarry Smith 
4101e07b27eSBarry Smith   /* setup */
4111e07b27eSBarry Smith   if (sred->pctelescope_setup_type) {
4121e07b27eSBarry Smith     ierr = sred->pctelescope_setup_type(pc,sred);CHKERRQ(ierr);
4131e07b27eSBarry Smith   }
4141e07b27eSBarry Smith   /* update */
4151e07b27eSBarry Smith   if (!pc->setupcalled) {
4161e07b27eSBarry Smith     if (sred->pctelescope_matcreate_type) {
4171e07b27eSBarry Smith       ierr = sred->pctelescope_matcreate_type(pc,sred,MAT_INITIAL_MATRIX,&sred->Bred);CHKERRQ(ierr);
4181e07b27eSBarry Smith     }
4191e07b27eSBarry Smith     if (sred->pctelescope_matnullspacecreate_type) {
420*392968a1SPatrick Sanan       ierr = sred->pctelescope_matnullspacecreate_type(pc,sred,sred->Bred);CHKERRQ(ierr);
4211e07b27eSBarry Smith     }
4221e07b27eSBarry Smith   } else {
4231e07b27eSBarry Smith     if (sred->pctelescope_matcreate_type) {
4241e07b27eSBarry Smith       ierr = sred->pctelescope_matcreate_type(pc,sred,MAT_REUSE_MATRIX,&sred->Bred);CHKERRQ(ierr);
4251e07b27eSBarry Smith     }
4261e07b27eSBarry Smith   }
4271e07b27eSBarry Smith 
4281e07b27eSBarry Smith   /* common - no construction */
4291e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
4301e07b27eSBarry Smith     ierr = KSPSetOperators(sred->ksp,sred->Bred,sred->Bred);CHKERRQ(ierr);
4311e07b27eSBarry Smith     if (pc->setfromoptionscalled && !pc->setupcalled){
4321e07b27eSBarry Smith       ierr = KSPSetFromOptions(sred->ksp);CHKERRQ(ierr);
4331e07b27eSBarry Smith     }
4341e07b27eSBarry Smith   }
4351e07b27eSBarry Smith   PetscFunctionReturn(0);
4361e07b27eSBarry Smith }
4371e07b27eSBarry Smith 
4381e07b27eSBarry Smith #undef __FUNCT__
4391e07b27eSBarry Smith #define __FUNCT__ "PCApply_Telescope"
4401e07b27eSBarry Smith static PetscErrorCode PCApply_Telescope(PC pc,Vec x,Vec y)
4411e07b27eSBarry Smith {
4421e07b27eSBarry Smith   PC_Telescope      sred = (PC_Telescope)pc->data;
4431e07b27eSBarry Smith   PetscErrorCode    ierr;
4441e07b27eSBarry Smith   Vec               xtmp,xred,yred;
44513c30530SDave May   PetscInt          i,st,ed;
4461e07b27eSBarry Smith   VecScatter        scatter;
4471e07b27eSBarry Smith   PetscScalar       *array;
4481e07b27eSBarry Smith   const PetscScalar *x_array;
4491e07b27eSBarry Smith 
4501e07b27eSBarry Smith   PetscFunctionBegin;
4511e07b27eSBarry Smith   xtmp    = sred->xtmp;
4521e07b27eSBarry Smith   scatter = sred->scatter;
4531e07b27eSBarry Smith   xred    = sred->xred;
4541e07b27eSBarry Smith   yred    = sred->yred;
4551e07b27eSBarry Smith 
4561e07b27eSBarry Smith   /* pull in vector x->xtmp */
4571e07b27eSBarry Smith   ierr = VecScatterBegin(scatter,x,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4581e07b27eSBarry Smith   ierr = VecScatterEnd(scatter,x,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4591e07b27eSBarry Smith 
4601e07b27eSBarry Smith   /* copy vector entires into xred */
4611e07b27eSBarry Smith   ierr = VecGetArrayRead(xtmp,&x_array);CHKERRQ(ierr);
4621e07b27eSBarry Smith   if (xred) {
4631e07b27eSBarry Smith     PetscScalar *LA_xred;
4641e07b27eSBarry Smith     ierr = VecGetOwnershipRange(xred,&st,&ed);CHKERRQ(ierr);
4651e07b27eSBarry Smith     ierr = VecGetArray(xred,&LA_xred);CHKERRQ(ierr);
4661e07b27eSBarry Smith     for (i=0; i<ed-st; i++) {
4671e07b27eSBarry Smith       LA_xred[i] = x_array[i];
4681e07b27eSBarry Smith     }
4691e07b27eSBarry Smith     ierr = VecRestoreArray(xred,&LA_xred);CHKERRQ(ierr);
4701e07b27eSBarry Smith   }
4711e07b27eSBarry Smith   ierr = VecRestoreArrayRead(xtmp,&x_array);CHKERRQ(ierr);
4721e07b27eSBarry Smith   /* solve */
4731e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
4741e07b27eSBarry Smith     ierr = KSPSolve(sred->ksp,xred,yred);CHKERRQ(ierr);
4751e07b27eSBarry Smith   }
4761e07b27eSBarry Smith   /* return vector */
4771e07b27eSBarry Smith   ierr = VecGetArray(xtmp,&array);CHKERRQ(ierr);
4781e07b27eSBarry Smith   if (yred) {
4791e07b27eSBarry Smith     const PetscScalar *LA_yred;
4801e07b27eSBarry Smith     ierr = VecGetOwnershipRange(yred,&st,&ed);CHKERRQ(ierr);
4811e07b27eSBarry Smith     ierr = VecGetArrayRead(yred,&LA_yred);CHKERRQ(ierr);
4821e07b27eSBarry Smith     for (i=0; i<ed-st; i++) {
4831e07b27eSBarry Smith       array[i] = LA_yred[i];
4841e07b27eSBarry Smith     }
4851e07b27eSBarry Smith     ierr = VecRestoreArrayRead(yred,&LA_yred);CHKERRQ(ierr);
4861e07b27eSBarry Smith   }
4871e07b27eSBarry Smith   ierr = VecRestoreArray(xtmp,&array);CHKERRQ(ierr);
4881e07b27eSBarry Smith   ierr = VecScatterBegin(scatter,xtmp,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4891e07b27eSBarry Smith   ierr = VecScatterEnd(scatter,xtmp,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4901e07b27eSBarry Smith   PetscFunctionReturn(0);
4911e07b27eSBarry Smith }
4921e07b27eSBarry Smith 
4931e07b27eSBarry Smith #undef __FUNCT__
494f650675bSDave May #define __FUNCT__ "PCApplyRichardson_Telescope"
495f650675bSDave May static PetscErrorCode PCApplyRichardson_Telescope(PC pc,Vec x,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its,PetscBool zeroguess,PetscInt *outits,PCRichardsonConvergedReason *reason)
496f650675bSDave May {
497f650675bSDave May   PC_Telescope      sred = (PC_Telescope)pc->data;
498f650675bSDave May   PetscErrorCode    ierr;
499a1d91a28SDave May   Vec               xtmp,yred;
500f650675bSDave May   PetscInt          i,st,ed;
501f650675bSDave May   VecScatter        scatter;
502f650675bSDave May   const PetscScalar *x_array;
503f650675bSDave May   PetscBool         default_init_guess_value;
504f650675bSDave May 
505f650675bSDave May   PetscFunctionBegin;
506f650675bSDave May   xtmp    = sred->xtmp;
507f650675bSDave May   scatter = sred->scatter;
508f650675bSDave May   yred    = sred->yred;
509f650675bSDave May 
510f650675bSDave May   if (its > 1) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCApplyRichardson_Telescope only supports max_it = 1");
511f650675bSDave May   *reason = (PCRichardsonConvergedReason)0;
512f650675bSDave May 
513f650675bSDave May   if (!zeroguess) {
514f650675bSDave May     ierr = PetscInfo(pc,"PCTelescope: Scattering y for non-zero initial guess\n");CHKERRQ(ierr);
515f650675bSDave May     /* pull in vector y->xtmp */
516f650675bSDave May     ierr = VecScatterBegin(scatter,y,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
517f650675bSDave May     ierr = VecScatterEnd(scatter,y,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
518f650675bSDave May 
519f650675bSDave May     /* copy vector entires into xred */
520f650675bSDave May     ierr = VecGetArrayRead(xtmp,&x_array);CHKERRQ(ierr);
521f650675bSDave May     if (yred) {
522f650675bSDave May       PetscScalar *LA_yred;
523f650675bSDave May       ierr = VecGetOwnershipRange(yred,&st,&ed);CHKERRQ(ierr);
524f650675bSDave May       ierr = VecGetArray(yred,&LA_yred);CHKERRQ(ierr);
525f650675bSDave May       for (i=0; i<ed-st; i++) {
526f650675bSDave May         LA_yred[i] = x_array[i];
527f650675bSDave May       }
528f650675bSDave May       ierr = VecRestoreArray(yred,&LA_yred);CHKERRQ(ierr);
529f650675bSDave May     }
530f650675bSDave May     ierr = VecRestoreArrayRead(xtmp,&x_array);CHKERRQ(ierr);
531f650675bSDave May   }
532f650675bSDave May 
533f650675bSDave May   if (isActiveRank(sred->psubcomm)) {
534f650675bSDave May     ierr = KSPGetInitialGuessNonzero(sred->ksp,&default_init_guess_value);CHKERRQ(ierr);
535f650675bSDave May     if (!zeroguess) ierr = KSPSetInitialGuessNonzero(sred->ksp,PETSC_TRUE);CHKERRQ(ierr);
536f650675bSDave May   }
537f650675bSDave May 
538f650675bSDave May   ierr = PCApply_Telescope(pc,x,y);CHKERRQ(ierr);
539f650675bSDave May 
540f650675bSDave May   if (isActiveRank(sred->psubcomm)) {
541f650675bSDave May     ierr = KSPSetInitialGuessNonzero(sred->ksp,default_init_guess_value);CHKERRQ(ierr);
542f650675bSDave May   }
543f650675bSDave May 
544f650675bSDave May   if (!*reason) *reason = PCRICHARDSON_CONVERGED_ITS;
545f650675bSDave May   *outits = 1;
546f650675bSDave May   PetscFunctionReturn(0);
547f650675bSDave May }
548f650675bSDave May 
549f650675bSDave May #undef __FUNCT__
5501e07b27eSBarry Smith #define __FUNCT__ "PCReset_Telescope"
5511e07b27eSBarry Smith static PetscErrorCode PCReset_Telescope(PC pc)
5521e07b27eSBarry Smith {
5531e07b27eSBarry Smith   PC_Telescope   sred = (PC_Telescope)pc->data;
5541e07b27eSBarry Smith   PetscErrorCode ierr;
5551e07b27eSBarry Smith 
5561e07b27eSBarry Smith   ierr = ISDestroy(&sred->isin);CHKERRQ(ierr);
5571e07b27eSBarry Smith   ierr = VecScatterDestroy(&sred->scatter);CHKERRQ(ierr);
558e3acf2f7SBarry Smith   ierr = VecDestroy(&sred->xred);CHKERRQ(ierr);
559e3acf2f7SBarry Smith   ierr = VecDestroy(&sred->yred);CHKERRQ(ierr);
560e3acf2f7SBarry Smith   ierr = VecDestroy(&sred->xtmp);CHKERRQ(ierr);
561e3acf2f7SBarry Smith   ierr = MatDestroy(&sred->Bred);CHKERRQ(ierr);
562e3acf2f7SBarry Smith   ierr = KSPReset(sred->ksp);CHKERRQ(ierr);
5631e07b27eSBarry Smith   if (sred->pctelescope_reset_type) {
5641e07b27eSBarry Smith     ierr = sred->pctelescope_reset_type(pc);CHKERRQ(ierr);
5651e07b27eSBarry Smith   }
5661e07b27eSBarry Smith   PetscFunctionReturn(0);
5671e07b27eSBarry Smith }
5681e07b27eSBarry Smith 
5691e07b27eSBarry Smith #undef __FUNCT__
5701e07b27eSBarry Smith #define __FUNCT__ "PCDestroy_Telescope"
5711e07b27eSBarry Smith static PetscErrorCode PCDestroy_Telescope(PC pc)
5721e07b27eSBarry Smith {
5731e07b27eSBarry Smith   PC_Telescope     sred = (PC_Telescope)pc->data;
5741e07b27eSBarry Smith   PetscErrorCode   ierr;
5751e07b27eSBarry Smith 
5761e07b27eSBarry Smith   PetscFunctionBegin;
5771e07b27eSBarry Smith   ierr = PCReset_Telescope(pc);CHKERRQ(ierr);
578e3acf2f7SBarry Smith   ierr = KSPDestroy(&sred->ksp);CHKERRQ(ierr);
5791e07b27eSBarry Smith   ierr = PetscSubcommDestroy(&sred->psubcomm);CHKERRQ(ierr);
580e3acf2f7SBarry Smith   ierr = PetscFree(sred->dm_ctx);CHKERRQ(ierr);
581e3acf2f7SBarry Smith   ierr = PetscFree(pc->data);CHKERRQ(ierr);
5821e07b27eSBarry Smith   PetscFunctionReturn(0);
5831e07b27eSBarry Smith }
5841e07b27eSBarry Smith 
5851e07b27eSBarry Smith #undef __FUNCT__
5861e07b27eSBarry Smith #define __FUNCT__ "PCSetFromOptions_Telescope"
5874416b707SBarry Smith static PetscErrorCode PCSetFromOptions_Telescope(PetscOptionItems *PetscOptionsObject,PC pc)
5881e07b27eSBarry Smith {
5891e07b27eSBarry Smith   PC_Telescope     sred = (PC_Telescope)pc->data;
5901e07b27eSBarry Smith   PetscErrorCode   ierr;
5911e07b27eSBarry Smith   MPI_Comm         comm;
5921e07b27eSBarry Smith   PetscMPIInt      size;
59348a10b22SPatrick Sanan   PetscBool        flg;
59448a10b22SPatrick Sanan   PetscSubcommType subcommtype;
5951e07b27eSBarry Smith 
5961e07b27eSBarry Smith   PetscFunctionBegin;
5971e07b27eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
5981e07b27eSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
5991e07b27eSBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"Telescope options");CHKERRQ(ierr);
60048a10b22SPatrick Sanan   ierr = PetscOptionsEnum("-pc_telescope_subcomm_type","Subcomm type (interlaced or contiguous)","PCTelescopeSetSubcommType",PetscSubcommTypes,(PetscEnum)sred->subcommtype,(PetscEnum*)&subcommtype,&flg);CHKERRQ(ierr);
60148a10b22SPatrick Sanan   if (flg) {
60248a10b22SPatrick Sanan     ierr = PCTelescopeSetSubcommType(pc,subcommtype);CHKERRQ(ierr);
60348a10b22SPatrick Sanan   }
6041e07b27eSBarry Smith   ierr = PetscOptionsInt("-pc_telescope_reduction_factor","Factor to reduce comm size by","PCTelescopeSetReductionFactor",sred->redfactor,&sred->redfactor,0);CHKERRQ(ierr);
6051e07b27eSBarry Smith   if (sred->redfactor > size) SETERRQ(comm,PETSC_ERR_ARG_WRONG,"-pc_telescope_reduction_factor <= comm size");
6061e07b27eSBarry Smith   ierr = PetscOptionsBool("-pc_telescope_ignore_dm","Ignore any DM attached to the PC","PCTelescopeSetIgnoreDM",sred->ignore_dm,&sred->ignore_dm,0);CHKERRQ(ierr);
6077c5279cbSDave May   ierr = PetscOptionsBool("-pc_telescope_ignore_kspcomputeoperators","Ignore method used to compute A","PCTelescopeSetIgnoreKSPComputeOperators",sred->ignore_kspcomputeoperators,&sred->ignore_kspcomputeoperators,0);CHKERRQ(ierr);
6081e07b27eSBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
6091e07b27eSBarry Smith   PetscFunctionReturn(0);
6101e07b27eSBarry Smith }
6111e07b27eSBarry Smith 
6121e07b27eSBarry Smith /* PC simplementation specific API's */
6131e07b27eSBarry Smith 
61448a10b22SPatrick Sanan #undef __FUNCT__
61548a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeGetKSP_Telescope"
6161e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetKSP_Telescope(PC pc,KSP *ksp)
6171e07b27eSBarry Smith {
6181e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
619bd49479cSSatish Balay   PetscFunctionBegin;
6201e07b27eSBarry Smith   if (ksp) *ksp = red->ksp;
621bd49479cSSatish Balay   PetscFunctionReturn(0);
6221e07b27eSBarry Smith }
6231e07b27eSBarry Smith 
62448a10b22SPatrick Sanan #undef __FUNCT__
62548a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeGetSubcommType_Telescope"
62648a10b22SPatrick Sanan static PetscErrorCode PCTelescopeGetSubcommType_Telescope(PC pc,PetscSubcommType *subcommtype)
62748a10b22SPatrick Sanan {
62848a10b22SPatrick Sanan   PC_Telescope red = (PC_Telescope)pc->data;
62948a10b22SPatrick Sanan   PetscFunctionBegin;
63048a10b22SPatrick Sanan   if (subcommtype) *subcommtype = red->subcommtype;
63148a10b22SPatrick Sanan   PetscFunctionReturn(0);
63248a10b22SPatrick Sanan }
63348a10b22SPatrick Sanan 
63448a10b22SPatrick Sanan #undef __FUNCT__
63548a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeSetSubcommType_Telescope"
63648a10b22SPatrick Sanan static PetscErrorCode PCTelescopeSetSubcommType_Telescope(PC pc,PetscSubcommType subcommtype)
63748a10b22SPatrick Sanan {
63848a10b22SPatrick Sanan   PC_Telescope     red = (PC_Telescope)pc->data;
63948a10b22SPatrick Sanan 
64048a10b22SPatrick Sanan   PetscFunctionBegin;
64148a10b22SPatrick Sanan   if (pc->setupcalled) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"You cannot change the subcommunicator type for PCTelescope after it has been set up.");
64248a10b22SPatrick Sanan   red->subcommtype = subcommtype;
64348a10b22SPatrick Sanan   PetscFunctionReturn(0);
64448a10b22SPatrick Sanan }
64548a10b22SPatrick Sanan 
64648a10b22SPatrick Sanan #undef __FUNCT__
64748a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeGetReductionFactor_Telescope"
6481e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetReductionFactor_Telescope(PC pc,PetscInt *fact)
6491e07b27eSBarry Smith {
6501e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
651bd49479cSSatish Balay   PetscFunctionBegin;
6521e07b27eSBarry Smith   if (fact) *fact = red->redfactor;
653bd49479cSSatish Balay   PetscFunctionReturn(0);
6541e07b27eSBarry Smith }
6551e07b27eSBarry Smith 
65648a10b22SPatrick Sanan #undef __FUNCT__
65748a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeSetReductionFactor_Telescope"
6581e07b27eSBarry Smith static PetscErrorCode PCTelescopeSetReductionFactor_Telescope(PC pc,PetscInt fact)
6591e07b27eSBarry Smith {
6601e07b27eSBarry Smith   PC_Telescope     red = (PC_Telescope)pc->data;
6611e07b27eSBarry Smith   PetscMPIInt      size;
6621e07b27eSBarry Smith   PetscErrorCode   ierr;
6631e07b27eSBarry Smith 
664bd49479cSSatish Balay   PetscFunctionBegin;
6651e07b27eSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
6661e07b27eSBarry Smith   if (fact <= 0) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Reduction factor of telescoping PC %D must be positive",fact);
6671e07b27eSBarry Smith   if (fact > size) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Reduction factor of telescoping PC %D must be <= comm.size",fact);
6681e07b27eSBarry Smith   red->redfactor = fact;
669bd49479cSSatish Balay   PetscFunctionReturn(0);
6701e07b27eSBarry Smith }
6711e07b27eSBarry Smith 
67248a10b22SPatrick Sanan #undef __FUNCT__
67348a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeGetIgnoreDM_Telescope"
6741e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetIgnoreDM_Telescope(PC pc,PetscBool *v)
6751e07b27eSBarry Smith {
6761e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
677bd49479cSSatish Balay   PetscFunctionBegin;
6781e07b27eSBarry Smith   if (v) *v = red->ignore_dm;
679bd49479cSSatish Balay   PetscFunctionReturn(0);
6801e07b27eSBarry Smith }
68148a10b22SPatrick Sanan 
68248a10b22SPatrick Sanan #undef __FUNCT__
68348a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeSetIgnoreDM_Telescope"
6841e07b27eSBarry Smith static PetscErrorCode PCTelescopeSetIgnoreDM_Telescope(PC pc,PetscBool v)
6851e07b27eSBarry Smith {
6861e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
687bd49479cSSatish Balay   PetscFunctionBegin;
6881e07b27eSBarry Smith   red->ignore_dm = v;
689bd49479cSSatish Balay   PetscFunctionReturn(0);
6901e07b27eSBarry Smith }
6911e07b27eSBarry Smith 
69248a10b22SPatrick Sanan #undef __FUNCT__
69348a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeGetIgnoreKSPComputeOperators_Telescope"
6940ae7c45bSDave May static PetscErrorCode PCTelescopeGetIgnoreKSPComputeOperators_Telescope(PC pc,PetscBool *v)
6950ae7c45bSDave May {
6960ae7c45bSDave May   PC_Telescope red = (PC_Telescope)pc->data;
6970ae7c45bSDave May   PetscFunctionBegin;
6980ae7c45bSDave May   if (v) *v = red->ignore_kspcomputeoperators;
6990ae7c45bSDave May   PetscFunctionReturn(0);
7000ae7c45bSDave May }
70148a10b22SPatrick Sanan 
70248a10b22SPatrick Sanan #undef __FUNCT__
70348a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeSetIgnoreKSPComputeOperators_Telescope"
7040ae7c45bSDave May static PetscErrorCode PCTelescopeSetIgnoreKSPComputeOperators_Telescope(PC pc,PetscBool v)
7050ae7c45bSDave May {
7060ae7c45bSDave May   PC_Telescope red = (PC_Telescope)pc->data;
7070ae7c45bSDave May   PetscFunctionBegin;
7080ae7c45bSDave May   red->ignore_kspcomputeoperators = v;
7090ae7c45bSDave May   PetscFunctionReturn(0);
7100ae7c45bSDave May }
7110ae7c45bSDave May 
71248a10b22SPatrick Sanan #undef __FUNCT__
71348a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeGetDM_Telescope"
7141e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetDM_Telescope(PC pc,DM *dm)
7151e07b27eSBarry Smith {
7161e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
717bd49479cSSatish Balay   PetscFunctionBegin;
7181e07b27eSBarry Smith   *dm = private_PCTelescopeGetSubDM(red);
719bd49479cSSatish Balay   PetscFunctionReturn(0);
7201e07b27eSBarry Smith }
7211e07b27eSBarry Smith 
7220f43ea10SBarry Smith #undef __FUNCT__
7230f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeGetKSP"
7241e07b27eSBarry Smith /*@
7251e07b27eSBarry Smith  PCTelescopeGetKSP - Gets the KSP created by the telescoping PC.
7261e07b27eSBarry Smith 
7271e07b27eSBarry Smith  Not Collective
7281e07b27eSBarry Smith 
7291e07b27eSBarry Smith  Input Parameter:
7301e07b27eSBarry Smith .  pc - the preconditioner context
7311e07b27eSBarry Smith 
7321e07b27eSBarry Smith  Output Parameter:
7331e07b27eSBarry Smith .  subksp - the KSP defined the smaller set of processes
7341e07b27eSBarry Smith 
7351e07b27eSBarry Smith  Level: advanced
7361e07b27eSBarry Smith 
7371e07b27eSBarry Smith .keywords: PC, telescopting solve
7381e07b27eSBarry Smith @*/
7391e07b27eSBarry Smith PetscErrorCode PCTelescopeGetKSP(PC pc,KSP *subksp)
7401e07b27eSBarry Smith {
741bd49479cSSatish Balay   PetscErrorCode ierr;
742bd49479cSSatish Balay   PetscFunctionBegin;
743163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetKSP_C",(PC,KSP*),(pc,subksp));CHKERRQ(ierr);
744bd49479cSSatish Balay   PetscFunctionReturn(0);
7451e07b27eSBarry Smith }
7461e07b27eSBarry Smith 
7470f43ea10SBarry Smith #undef __FUNCT__
7480f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeGetReductionFactor"
7491e07b27eSBarry Smith /*@
7501e07b27eSBarry Smith  PCTelescopeGetReductionFactor - Gets the factor by which the original number of processes has been reduced by.
7511e07b27eSBarry Smith 
7521e07b27eSBarry Smith  Not Collective
7531e07b27eSBarry Smith 
7541e07b27eSBarry Smith  Input Parameter:
7551e07b27eSBarry Smith .  pc - the preconditioner context
7561e07b27eSBarry Smith 
7571e07b27eSBarry Smith  Output Parameter:
7581e07b27eSBarry Smith .  fact - the reduction factor
7591e07b27eSBarry Smith 
7601e07b27eSBarry Smith  Level: advanced
7611e07b27eSBarry Smith 
7621e07b27eSBarry Smith .keywords: PC, telescoping solve
7631e07b27eSBarry Smith @*/
7641e07b27eSBarry Smith PetscErrorCode PCTelescopeGetReductionFactor(PC pc,PetscInt *fact)
7651e07b27eSBarry Smith {
766bd49479cSSatish Balay   PetscErrorCode ierr;
767bd49479cSSatish Balay   PetscFunctionBegin;
768163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetReductionFactor_C",(PC,PetscInt*),(pc,fact));CHKERRQ(ierr);
769bd49479cSSatish Balay   PetscFunctionReturn(0);
7701e07b27eSBarry Smith }
7711e07b27eSBarry Smith 
7720f43ea10SBarry Smith #undef __FUNCT__
7730f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeSetReductionFactor"
7741e07b27eSBarry Smith /*@
7751e07b27eSBarry Smith  PCTelescopeSetReductionFactor - Sets the factor by which the original number of processes has been reduced by.
7761e07b27eSBarry Smith 
7771e07b27eSBarry Smith  Not Collective
7781e07b27eSBarry Smith 
7791e07b27eSBarry Smith  Input Parameter:
7801e07b27eSBarry Smith .  pc - the preconditioner context
7811e07b27eSBarry Smith 
7821e07b27eSBarry Smith  Output Parameter:
7831e07b27eSBarry Smith .  fact - the reduction factor
7841e07b27eSBarry Smith 
7851e07b27eSBarry Smith  Level: advanced
7861e07b27eSBarry Smith 
7871e07b27eSBarry Smith .keywords: PC, telescoping solve
7881e07b27eSBarry Smith @*/
7891e07b27eSBarry Smith PetscErrorCode PCTelescopeSetReductionFactor(PC pc,PetscInt fact)
7901e07b27eSBarry Smith {
791bd49479cSSatish Balay   PetscErrorCode ierr;
792bd49479cSSatish Balay   PetscFunctionBegin;
793bd49479cSSatish Balay   ierr = PetscTryMethod(pc,"PCTelescopeSetReductionFactor_C",(PC,PetscInt),(pc,fact));CHKERRQ(ierr);
794bd49479cSSatish Balay   PetscFunctionReturn(0);
7951e07b27eSBarry Smith }
7961e07b27eSBarry Smith 
7970f43ea10SBarry Smith #undef __FUNCT__
7980f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeGetIgnoreDM"
7991e07b27eSBarry Smith /*@
8001e07b27eSBarry Smith  PCTelescopeGetIgnoreDM - Get the flag indicating if any DM attached to the PC will be used.
8011e07b27eSBarry Smith 
8021e07b27eSBarry Smith  Not Collective
8031e07b27eSBarry Smith 
8041e07b27eSBarry Smith  Input Parameter:
8051e07b27eSBarry Smith .  pc - the preconditioner context
8061e07b27eSBarry Smith 
8071e07b27eSBarry Smith  Output Parameter:
8081e07b27eSBarry Smith .  v - the flag
8091e07b27eSBarry Smith 
8101e07b27eSBarry Smith  Level: advanced
8111e07b27eSBarry Smith 
8121e07b27eSBarry Smith .keywords: PC, telescoping solve
8131e07b27eSBarry Smith @*/
8141e07b27eSBarry Smith PetscErrorCode PCTelescopeGetIgnoreDM(PC pc,PetscBool *v)
8151e07b27eSBarry Smith {
816bd49479cSSatish Balay   PetscErrorCode ierr;
817bd49479cSSatish Balay   PetscFunctionBegin;
818163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetIgnoreDM_C",(PC,PetscBool*),(pc,v));CHKERRQ(ierr);
819bd49479cSSatish Balay   PetscFunctionReturn(0);
8201e07b27eSBarry Smith }
8211e07b27eSBarry Smith 
8220f43ea10SBarry Smith #undef __FUNCT__
8230f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeSetIgnoreDM"
8241e07b27eSBarry Smith /*@
8251e07b27eSBarry Smith  PCTelescopeSetIgnoreDM - Set a flag to ignore any DM attached to the PC.
8261e07b27eSBarry Smith 
8271e07b27eSBarry Smith  Not Collective
8281e07b27eSBarry Smith 
8291e07b27eSBarry Smith  Input Parameter:
8301e07b27eSBarry Smith .  pc - the preconditioner context
8311e07b27eSBarry Smith 
8321e07b27eSBarry Smith  Output Parameter:
8331e07b27eSBarry Smith .  v - Use PETSC_TRUE to ignore any DM
8341e07b27eSBarry Smith 
8351e07b27eSBarry Smith  Level: advanced
8361e07b27eSBarry Smith 
8371e07b27eSBarry Smith .keywords: PC, telescoping solve
8381e07b27eSBarry Smith @*/
839bfd6bcc6SSatish Balay PetscErrorCode PCTelescopeSetIgnoreDM(PC pc,PetscBool v)
8401e07b27eSBarry Smith {
841bd49479cSSatish Balay   PetscErrorCode ierr;
842bd49479cSSatish Balay   PetscFunctionBegin;
843bd49479cSSatish Balay   ierr = PetscTryMethod(pc,"PCTelescopeSetIgnoreDM_C",(PC,PetscBool),(pc,v));CHKERRQ(ierr);
844bd49479cSSatish Balay   PetscFunctionReturn(0);
8451e07b27eSBarry Smith }
8461e07b27eSBarry Smith 
8470f43ea10SBarry Smith #undef __FUNCT__
8480f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeGetIgnoreKSPComputeOperators"
8491e07b27eSBarry Smith /*@
8500ae7c45bSDave May  PCTelescopeGetIgnoreKSPComputeOperators - Get the flag indicating if KSPComputeOperators will be used.
8510ae7c45bSDave May 
8520ae7c45bSDave May  Not Collective
8530ae7c45bSDave May 
8540ae7c45bSDave May  Input Parameter:
8550ae7c45bSDave May .  pc - the preconditioner context
8560ae7c45bSDave May 
8570ae7c45bSDave May  Output Parameter:
8580ae7c45bSDave May .  v - the flag
8590ae7c45bSDave May 
8600ae7c45bSDave May  Level: advanced
8610ae7c45bSDave May 
8620ae7c45bSDave May .keywords: PC, telescoping solve
8630ae7c45bSDave May @*/
8640ae7c45bSDave May PetscErrorCode PCTelescopeGetIgnoreKSPComputeOperators(PC pc,PetscBool *v)
8650ae7c45bSDave May {
8660ae7c45bSDave May   PetscErrorCode ierr;
8670ae7c45bSDave May   PetscFunctionBegin;
868163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetIgnoreKSPComputeOperators_C",(PC,PetscBool*),(pc,v));CHKERRQ(ierr);
8690ae7c45bSDave May   PetscFunctionReturn(0);
8700ae7c45bSDave May }
8710ae7c45bSDave May 
8720f43ea10SBarry Smith #undef __FUNCT__
8730f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeSetIgnoreKSPComputeOperators"
8740ae7c45bSDave May /*@
8750ae7c45bSDave May  PCTelescopeSetIgnoreKSPComputeOperators - Set a flag to ignore KSPComputeOperators.
8760ae7c45bSDave May 
8770ae7c45bSDave May  Not Collective
8780ae7c45bSDave May 
8790ae7c45bSDave May  Input Parameter:
8800ae7c45bSDave May .  pc - the preconditioner context
8810ae7c45bSDave May 
8820ae7c45bSDave May  Output Parameter:
883a954d8f4SDave May .  v - Use PETSC_TRUE to ignore the method (if defined) set via KSPSetComputeOperators on pc
8840ae7c45bSDave May 
8850ae7c45bSDave May  Level: advanced
8860ae7c45bSDave May 
8870ae7c45bSDave May .keywords: PC, telescoping solve
8880ae7c45bSDave May @*/
8890ae7c45bSDave May PetscErrorCode PCTelescopeSetIgnoreKSPComputeOperators(PC pc,PetscBool v)
8900ae7c45bSDave May {
8910ae7c45bSDave May   PetscErrorCode ierr;
8920ae7c45bSDave May   PetscFunctionBegin;
8930ae7c45bSDave May   ierr = PetscTryMethod(pc,"PCTelescopeSetIgnoreKSPComputeOperators_C",(PC,PetscBool),(pc,v));CHKERRQ(ierr);
8940ae7c45bSDave May   PetscFunctionReturn(0);
8950ae7c45bSDave May }
8960ae7c45bSDave May 
8970f43ea10SBarry Smith #undef __FUNCT__
8980f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeGetDM"
8990ae7c45bSDave May /*@
9001e07b27eSBarry Smith  PCTelescopeGetDM - Get the re-partitioned DM attached to the sub KSP.
9011e07b27eSBarry Smith 
9021e07b27eSBarry Smith  Not Collective
9031e07b27eSBarry Smith 
9041e07b27eSBarry Smith  Input Parameter:
9051e07b27eSBarry Smith .  pc - the preconditioner context
9061e07b27eSBarry Smith 
9071e07b27eSBarry Smith  Output Parameter:
9081e07b27eSBarry Smith .  subdm - The re-partitioned DM
9091e07b27eSBarry Smith 
9101e07b27eSBarry Smith  Level: advanced
9111e07b27eSBarry Smith 
9121e07b27eSBarry Smith .keywords: PC, telescoping solve
9131e07b27eSBarry Smith @*/
9141e07b27eSBarry Smith PetscErrorCode PCTelescopeGetDM(PC pc,DM *subdm)
9151e07b27eSBarry Smith {
916bd49479cSSatish Balay   PetscErrorCode ierr;
917bd49479cSSatish Balay   PetscFunctionBegin;
918163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetDM_C",(PC,DM*),(pc,subdm));CHKERRQ(ierr);
919bd49479cSSatish Balay   PetscFunctionReturn(0);
9201e07b27eSBarry Smith }
9211e07b27eSBarry Smith 
9220f43ea10SBarry Smith #undef __FUNCT__
9230f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeSetSubcommType"
92448a10b22SPatrick Sanan /*@
92548a10b22SPatrick Sanan  PCTelescopeSetSubcommType - set subcommunicator type (interlaced or contiguous)
92648a10b22SPatrick Sanan 
92748a10b22SPatrick Sanan  Logically Collective
92848a10b22SPatrick Sanan 
92948a10b22SPatrick Sanan  Input Parameter:
9301dae98e4SBarry Smith +  pc - the preconditioner context
9311dae98e4SBarry Smith -  subcommtype - the subcommunicator type (see PetscSubcommType)
93248a10b22SPatrick Sanan 
93348a10b22SPatrick Sanan  Level: advanced
93448a10b22SPatrick Sanan 
93548a10b22SPatrick Sanan .keywords: PC, telescoping solve
93648a10b22SPatrick Sanan 
93748a10b22SPatrick Sanan .seealso: PetscSubcommType, PetscSubcomm, PCTELESCOPE
93848a10b22SPatrick Sanan @*/
93948a10b22SPatrick Sanan PetscErrorCode PCTelescopeSetSubcommType(PC pc, PetscSubcommType subcommtype)
94048a10b22SPatrick Sanan {
94148a10b22SPatrick Sanan   PetscErrorCode ierr;
94248a10b22SPatrick Sanan   PetscFunctionBegin;
94348a10b22SPatrick Sanan   ierr = PetscTryMethod(pc,"PCTelescopeSetSubcommType_C",(PC,PetscSubcommType),(pc,subcommtype));CHKERRQ(ierr);
94448a10b22SPatrick Sanan   PetscFunctionReturn(0);
94548a10b22SPatrick Sanan }
94648a10b22SPatrick Sanan 
9470f43ea10SBarry Smith #undef __FUNCT__
9481dae98e4SBarry Smith #define __FUNCT__ "PCTelescopeGetSubcommType"
94948a10b22SPatrick Sanan /*@
95048a10b22SPatrick Sanan  PCTelescopeGetSubcommType - Get the subcommunicator type (interlaced or contiguous)
95148a10b22SPatrick Sanan 
95248a10b22SPatrick Sanan  Not Collective
95348a10b22SPatrick Sanan 
95448a10b22SPatrick Sanan  Input Parameter:
95548a10b22SPatrick Sanan .  pc - the preconditioner context
95648a10b22SPatrick Sanan 
95748a10b22SPatrick Sanan  Output Parameter:
95848a10b22SPatrick Sanan .  subcommtype - the subcommunicator type (see PetscSubcommType)
95948a10b22SPatrick Sanan 
96048a10b22SPatrick Sanan  Level: advanced
96148a10b22SPatrick Sanan 
96248a10b22SPatrick Sanan .keywords: PC, telescoping solve
96348a10b22SPatrick Sanan 
9641dae98e4SBarry Smith .seealso: PetscSubcomm, PetscSubcommType, PCTELESCOPE
96548a10b22SPatrick Sanan @*/
9661dae98e4SBarry Smith PetscErrorCode PCTelescopeGetSubcommType(PC pc, PetscSubcommType *subcommtype)
96748a10b22SPatrick Sanan {
96848a10b22SPatrick Sanan   PetscErrorCode ierr;
96948a10b22SPatrick Sanan   PetscFunctionBegin;
97048a10b22SPatrick Sanan   ierr = PetscUseMethod(pc,"PCTelescopeGetSubcommType_C",(PC,PetscSubcommType*),(pc,subcommtype));CHKERRQ(ierr);
97148a10b22SPatrick Sanan   PetscFunctionReturn(0);
97248a10b22SPatrick Sanan }
97348a10b22SPatrick Sanan 
9741e07b27eSBarry Smith /* -------------------------------------------------------------------------------------*/
9751e07b27eSBarry Smith /*MC
9761e07b27eSBarry Smith    PCTELESCOPE - Runs a KSP solver on a sub-group of processors. MPI processes not in the sub-communicator are idle during the solve.
9771e07b27eSBarry Smith 
9781e07b27eSBarry Smith    Options Database:
979a04a6428SPatrick Sanan +  -pc_telescope_reduction_factor <r> - factor to use communicator size by. e.g. with 64 MPI processes and r=4, the new sub-communicator will have 64/4 = 16 ranks.
980a04a6428SPatrick Sanan -  -pc_telescope_ignore_dm  - flag to indicate whether an attached DM should be ignored
981a04a6428SPatrick Sanan -  -pc_telescope_subcomm_type <interlaced,contiguous> - how to define the reduced communicator. see PetscSubcomm for more.
9821e07b27eSBarry Smith 
9831e07b27eSBarry Smith    Level: advanced
9841e07b27eSBarry Smith 
9851e07b27eSBarry Smith    Notes:
9866fc41876SBarry Smith    The preconditioner is deemed telescopic as it only calls KSPSolve() on a single
9878439623fSPatrick Sanan    sub-communicator, in contrast with PCREDUNDANT which calls KSPSolve() on N sub-communicators.
9888439623fSPatrick Sanan    This means there will be MPI processes which will be idle during the application of this preconditioner.
9896fc41876SBarry Smith 
9901e07b27eSBarry Smith    The default KSP is PREONLY. If a DM is attached to the PC, it is re-partitioned on the sub-communicator.
9911e07b27eSBarry Smith    Both the Bmat operator and the right hand side vector are permuted into the new DOF ordering defined by the re-partitioned DM.
9921e07b27eSBarry Smith    Currently only support for re-partitioning a DMDA is provided.
9938439623fSPatrick Sanan    Any nullspace attached to the original Bmat operator is extracted, re-partitioned and set on the repartitioned Bmat operator.
9941e07b27eSBarry Smith    KSPSetComputeOperators() is not propagated to the sub KSP.
9951e07b27eSBarry Smith    Currently there is no support for the flag -pc_use_amat
9961e07b27eSBarry Smith 
9976fc41876SBarry Smith    Assuming that the parent preconditioner (PC) is defined on a communicator c, this implementation
9988439623fSPatrick Sanan    creates a child sub-communicator (c') containing fewer MPI processes than the original parent preconditioner (PC).
9996fc41876SBarry Smith 
10006fc41876SBarry Smith   Developer Notes:
10016fc41876SBarry Smith    During PCSetup, the B operator is scattered onto c'.
10026fc41876SBarry Smith    Within PCApply, the RHS vector (x) is scattered into a redundant vector, xred (defined on c').
10038439623fSPatrick Sanan    Then, KSPSolve() is executed on the c' communicator.
10046fc41876SBarry Smith 
10056fc41876SBarry Smith    The communicator used within the telescoping preconditioner is defined by a PetscSubcomm using the INTERLACED
1006a04a6428SPatrick Sanan    creation routine by default (this can be changed with -pc_telescope_subcomm_type). We run the sub KSP on only the ranks within the communicator which have a color equal to zero.
10076fc41876SBarry Smith 
1008005d9f20SPatrick Sanan    The telescoping preconditioner is aware of nullspaces and near nullspaces which are attached to the B operator.
10098439623fSPatrick Sanan    In the case where B has a (near) nullspace attached, the (near) nullspace vectors are extracted from B and mapped into
1010005d9f20SPatrick Sanan    a new (near) nullspace, defined on the sub-communicator, which is attached to B' (the B operator which was scattered to c')
10116fc41876SBarry Smith 
10126fc41876SBarry Smith    The telescoping preconditioner is aware of an attached DM. In the event that the DM is of type DMDA (2D or 3D -
10136fc41876SBarry Smith    1D support for 1D DMDAs is not provided), a new DMDA is created on c' (e.g. it is re-partitioned), and this new DM
10146fc41876SBarry Smith    is attached the sub KSPSolve(). The design of telescope is such that it should be possible to extend support
10158439623fSPatrick Sanan    for re-partitioning other to DM's (e.g. DMPLEX). The user can supply a flag to ignore attached DMs.
10166fc41876SBarry Smith 
10176fc41876SBarry Smith    By default, B' is defined by simply fusing rows from different MPI processes
10186fc41876SBarry Smith 
10198439623fSPatrick Sanan    When a DMDA is attached to the parent preconditioner, B' is defined by: (i) performing a symmetric permutation of B
10206fc41876SBarry Smith    into the ordering defined by the DMDA on c', (ii) extracting the local chunks via MatGetSubMatrices(), (iii) fusing the
10216fc41876SBarry Smith    locally (sequential) matrices defined on the ranks common to c and c' into B' using MatCreateMPIMatConcatenateSeqMat()
10226fc41876SBarry Smith 
10238439623fSPatrick Sanan    Limitations/improvements include the following.
10248439623fSPatrick Sanan    VecPlaceArray() could be used within PCApply() to improve efficiency and reduce memory usage.
10256fc41876SBarry Smith 
10266fc41876SBarry Smith    The symmetric permutation used when a DMDA is encountered is performed via explicitly assmbleming a permutation matrix P,
10278439623fSPatrick Sanan    and performing P^T.A.P. Possibly it might be more efficient to use MatPermute(). We opted to use P^T.A.P as it appears
10288439623fSPatrick Sanan    VecPermute() does not supported for the use case required here. By computing P, one can permute both the operator and RHS in a
10296fc41876SBarry Smith    consistent manner.
10306fc41876SBarry Smith 
10318439623fSPatrick Sanan    Mapping of vectors is performed in the following way.
10328439623fSPatrick Sanan    Suppose the parent comm size was 4, and we set a reduction factor of 2; this would give a comm size on c' of 2.
10338439623fSPatrick Sanan    Using the interlaced creation routine, the ranks in c with color = 0 will be rank 0 and 2.
10348439623fSPatrick Sanan    We perform the scatter to the sub-comm in the following way.
10356fc41876SBarry Smith    [1] Given a vector x defined on comm c
10366fc41876SBarry Smith 
10376fc41876SBarry Smith    rank(c) : _________ 0 ______  ________ 1 _______  ________ 2 _____________ ___________ 3 __________
10386fc41876SBarry Smith          x : [0, 1, 2, 3, 4, 5] [6, 7, 8, 9, 10, 11] [12, 13, 14, 15, 16, 17] [18, 19, 20, 21, 22, 23]
10396fc41876SBarry Smith 
10406fc41876SBarry Smith    scatter to xtmp defined also on comm c so that we have the following values
10416fc41876SBarry Smith 
10426fc41876SBarry Smith    rank(c) : ___________________ 0 ________________  _1_  ______________________ 2 _______________________  __3_
10436fc41876SBarry Smith       xtmp : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] [  ] [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23] [  ]
10446fc41876SBarry Smith 
10456fc41876SBarry Smith    The entries on rank 1 and 3 (ranks which do not have a color = 0 in c') have no values
10466fc41876SBarry Smith 
10476fc41876SBarry Smith 
10486fc41876SBarry Smith    [2] Copy the value from rank 0, 2 (indices with respect to comm c) into the vector xred which is defined on communicator c'.
10496fc41876SBarry Smith    Ranks 0 and 2 are the only ranks in the subcomm which have a color = 0.
10506fc41876SBarry Smith 
10516fc41876SBarry Smith     rank(c') : ___________________ 0 _______________  ______________________ 1 _____________________
10526fc41876SBarry Smith       xred : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]
10536fc41876SBarry Smith 
10541e07b27eSBarry Smith 
10551e07b27eSBarry Smith   Contributed by Dave May
10561e07b27eSBarry Smith 
10576fc41876SBarry Smith .seealso:  PCTelescopeGetKSP(), PCTelescopeGetDM(), PCTelescopeGetReductionFactor(), PCTelescopeSetReductionFactor(), PCTelescopeGetIgnoreDM(), PCTelescopeSetIgnoreDM(), PCREDUNDANT
10581e07b27eSBarry Smith M*/
10591e07b27eSBarry Smith #undef __FUNCT__
10601e07b27eSBarry Smith #define __FUNCT__ "PCCreate_Telescope"
10611e07b27eSBarry Smith PETSC_EXTERN PetscErrorCode PCCreate_Telescope(PC pc)
10621e07b27eSBarry Smith {
10631e07b27eSBarry Smith   PetscErrorCode       ierr;
10641e07b27eSBarry Smith   struct _PC_Telescope *sred;
10651e07b27eSBarry Smith 
10661e07b27eSBarry Smith   PetscFunctionBegin;
10671e07b27eSBarry Smith   ierr = PetscNewLog(pc,&sred);CHKERRQ(ierr);
106848a10b22SPatrick Sanan   sred->subcommtype    = PETSC_SUBCOMM_INTERLACED;
10691e07b27eSBarry Smith   sred->redfactor      = 1;
10701e07b27eSBarry Smith   sred->ignore_dm      = PETSC_FALSE;
10717c5279cbSDave May   sred->ignore_kspcomputeoperators = PETSC_FALSE;
10721e07b27eSBarry Smith   pc->data             = (void*)sred;
10731e07b27eSBarry Smith 
10741e07b27eSBarry Smith   pc->ops->apply           = PCApply_Telescope;
10751e07b27eSBarry Smith   pc->ops->applytranspose  = NULL;
1076f650675bSDave May   pc->ops->applyrichardson = PCApplyRichardson_Telescope;
10771e07b27eSBarry Smith   pc->ops->setup           = PCSetUp_Telescope;
10781e07b27eSBarry Smith   pc->ops->destroy         = PCDestroy_Telescope;
10791e07b27eSBarry Smith   pc->ops->reset           = PCReset_Telescope;
10801e07b27eSBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_Telescope;
10811e07b27eSBarry Smith   pc->ops->view            = PCView_Telescope;
10821e07b27eSBarry Smith 
10831e07b27eSBarry Smith   sred->pctelescope_setup_type              = PCTelescopeSetUp_default;
10841e07b27eSBarry Smith   sred->pctelescope_matcreate_type          = PCTelescopeMatCreate_default;
10851e07b27eSBarry Smith   sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_default;
10861e07b27eSBarry Smith   sred->pctelescope_reset_type              = NULL;
10871e07b27eSBarry Smith 
10881e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetKSP_C",PCTelescopeGetKSP_Telescope);CHKERRQ(ierr);
108948a10b22SPatrick Sanan   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetSubcommType_C",PCTelescopeGetSubcommType_Telescope);CHKERRQ(ierr);
109048a10b22SPatrick Sanan   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetSubcommType_C",PCTelescopeSetSubcommType_Telescope);CHKERRQ(ierr);
10911e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetReductionFactor_C",PCTelescopeGetReductionFactor_Telescope);CHKERRQ(ierr);
10921e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetReductionFactor_C",PCTelescopeSetReductionFactor_Telescope);CHKERRQ(ierr);
10931e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetIgnoreDM_C",PCTelescopeGetIgnoreDM_Telescope);CHKERRQ(ierr);
10941e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetIgnoreDM_C",PCTelescopeSetIgnoreDM_Telescope);CHKERRQ(ierr);
10950ae7c45bSDave May   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetIgnoreKSPComputeOperators_C",PCTelescopeGetIgnoreKSPComputeOperators_Telescope);CHKERRQ(ierr);
10960ae7c45bSDave May   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetIgnoreKSPComputeOperators_C",PCTelescopeSetIgnoreKSPComputeOperators_Telescope);CHKERRQ(ierr);
10971e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetDM_C",PCTelescopeGetDM_Telescope);CHKERRQ(ierr);
10981e07b27eSBarry Smith   PetscFunctionReturn(0);
10991e07b27eSBarry Smith }
1100