xref: /petsc/src/ksp/pc/impls/telescope/telescope.c (revision 575a05926143c699a34610f4aae807483647ae9b)
11e07b27eSBarry Smith 
21e07b27eSBarry Smith 
31e07b27eSBarry Smith 
4120bdd93SDave May #include <petsc/private/matimpl.h>
56fc41876SBarry Smith #include <petsc/private/pcimpl.h>
61e07b27eSBarry Smith #include <petscksp.h> /*I "petscksp.h" I*/
71e07b27eSBarry Smith #include <petscdm.h> /*I "petscdm.h" I*/
81e07b27eSBarry Smith 
9*575a0592SBarry Smith #include "../src/ksp/pc/impls/telescope/telescope.h"
101e07b27eSBarry Smith 
111e07b27eSBarry Smith /*
121e07b27eSBarry Smith  PCTelescopeSetUp_default()
131e07b27eSBarry Smith  PCTelescopeMatCreate_default()
141e07b27eSBarry Smith 
151e07b27eSBarry Smith  default
161e07b27eSBarry Smith 
171e07b27eSBarry Smith  // scatter in
181e07b27eSBarry Smith  x(comm) -> xtmp(comm)
191e07b27eSBarry Smith 
201e07b27eSBarry Smith  xred(subcomm) <- xtmp
211e07b27eSBarry Smith  yred(subcomm)
221e07b27eSBarry Smith 
231e07b27eSBarry Smith  yred(subcomm) --> xtmp
241e07b27eSBarry Smith 
251e07b27eSBarry Smith  // scatter out
261e07b27eSBarry Smith  xtmp(comm) -> y(comm)
271e07b27eSBarry Smith */
281e07b27eSBarry Smith 
291e07b27eSBarry Smith PetscBool isActiveRank(PetscSubcomm scomm)
301e07b27eSBarry Smith {
311e07b27eSBarry Smith   if (scomm->color == 0) { return PETSC_TRUE; }
321e07b27eSBarry Smith   else { return PETSC_FALSE; }
331e07b27eSBarry Smith }
341e07b27eSBarry Smith 
351e07b27eSBarry Smith #undef __FUNCT__
361e07b27eSBarry Smith #define __FUNCT__ "private_PCTelescopeGetSubDM"
371e07b27eSBarry Smith DM private_PCTelescopeGetSubDM(PC_Telescope sred)
381e07b27eSBarry Smith {
39c6a0d831SBarry Smith   DM subdm = NULL;
401e07b27eSBarry Smith 
411e07b27eSBarry Smith   if (!isActiveRank(sred->psubcomm)) { subdm = NULL; }
421e07b27eSBarry Smith   else {
431e07b27eSBarry Smith     switch (sred->sr_type) {
441e07b27eSBarry Smith     case TELESCOPE_DEFAULT: subdm = NULL;
451e07b27eSBarry Smith       break;
461e07b27eSBarry Smith     case TELESCOPE_DMDA:    subdm = ((PC_Telescope_DMDACtx*)sred->dm_ctx)->dmrepart;
471e07b27eSBarry Smith       break;
481e07b27eSBarry Smith     case TELESCOPE_DMPLEX:  subdm = NULL;
491e07b27eSBarry Smith       break;
501e07b27eSBarry Smith     }
511e07b27eSBarry Smith   }
521e07b27eSBarry Smith   return(subdm);
531e07b27eSBarry Smith }
541e07b27eSBarry Smith 
551e07b27eSBarry Smith #undef __FUNCT__
561e07b27eSBarry Smith #define __FUNCT__ "PCTelescopeSetUp_default"
571e07b27eSBarry Smith PetscErrorCode PCTelescopeSetUp_default(PC pc,PC_Telescope sred)
581e07b27eSBarry Smith {
591e07b27eSBarry Smith   PetscErrorCode ierr;
601e07b27eSBarry Smith   PetscInt       m,M,bs,st,ed;
611e07b27eSBarry Smith   Vec            x,xred,yred,xtmp;
621e07b27eSBarry Smith   Mat            B;
631e07b27eSBarry Smith   MPI_Comm       comm,subcomm;
641e07b27eSBarry Smith   VecScatter     scatter;
651e07b27eSBarry Smith   IS             isin;
661e07b27eSBarry Smith 
671e07b27eSBarry Smith   PetscFunctionBegin;
681e07b27eSBarry Smith   ierr = PetscInfo(pc,"PCTelescope: setup (default)\n");CHKERRQ(ierr);
691e07b27eSBarry Smith   comm = PetscSubcommParent(sred->psubcomm);
701e07b27eSBarry Smith   subcomm = PetscSubcommChild(sred->psubcomm);
711e07b27eSBarry Smith 
721e07b27eSBarry Smith   ierr = PCGetOperators(pc,NULL,&B);CHKERRQ(ierr);
731e07b27eSBarry Smith   ierr = MatGetSize(B,&M,NULL);CHKERRQ(ierr);
741e07b27eSBarry Smith   ierr = MatGetBlockSize(B,&bs);CHKERRQ(ierr);
751e07b27eSBarry Smith   ierr = MatCreateVecs(B,&x,NULL);CHKERRQ(ierr);
761e07b27eSBarry Smith 
771e07b27eSBarry Smith   xred = NULL;
783ac26c5eSBarry Smith   m    = 0;
791e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
801e07b27eSBarry Smith     ierr = VecCreate(subcomm,&xred);CHKERRQ(ierr);
811e07b27eSBarry Smith     ierr = VecSetSizes(xred,PETSC_DECIDE,M);CHKERRQ(ierr);
821e07b27eSBarry Smith     ierr = VecSetBlockSize(xred,bs);CHKERRQ(ierr);
831e07b27eSBarry Smith     ierr = VecSetFromOptions(xred);CHKERRQ(ierr);
84ca43db0aSBarry Smith     ierr = VecGetLocalSize(xred,&m);CHKERRQ(ierr);
851e07b27eSBarry Smith   }
861e07b27eSBarry Smith 
871e07b27eSBarry Smith   yred = NULL;
881e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
891e07b27eSBarry Smith     ierr = VecDuplicate(xred,&yred);CHKERRQ(ierr);
901e07b27eSBarry Smith   }
911e07b27eSBarry Smith 
921e07b27eSBarry Smith   ierr = VecCreate(comm,&xtmp);CHKERRQ(ierr);
931e07b27eSBarry Smith   ierr = VecSetSizes(xtmp,m,PETSC_DECIDE);CHKERRQ(ierr);
941e07b27eSBarry Smith   ierr = VecSetBlockSize(xtmp,bs);CHKERRQ(ierr);
951e07b27eSBarry Smith   ierr = VecSetType(xtmp,((PetscObject)x)->type_name);CHKERRQ(ierr);
961e07b27eSBarry Smith 
971e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
981e07b27eSBarry Smith     ierr = VecGetOwnershipRange(xred,&st,&ed);CHKERRQ(ierr);
991e07b27eSBarry Smith     ierr = ISCreateStride(comm,(ed-st),st,1,&isin);CHKERRQ(ierr);
1001e07b27eSBarry Smith   } else {
1011e07b27eSBarry Smith     ierr = VecGetOwnershipRange(x,&st,&ed);CHKERRQ(ierr);
1023ac26c5eSBarry Smith     ierr = ISCreateStride(comm,0,st,1,&isin);CHKERRQ(ierr);
1031e07b27eSBarry Smith   }
1041e07b27eSBarry Smith   ierr = ISSetBlockSize(isin,bs);CHKERRQ(ierr);
1051e07b27eSBarry Smith 
1061e07b27eSBarry Smith   ierr = VecScatterCreate(x,isin,xtmp,NULL,&scatter);CHKERRQ(ierr);
1071e07b27eSBarry Smith 
1081e07b27eSBarry Smith   sred->isin    = isin;
1091e07b27eSBarry Smith   sred->scatter = scatter;
1101e07b27eSBarry Smith   sred->xred    = xred;
1111e07b27eSBarry Smith   sred->yred    = yred;
1121e07b27eSBarry Smith   sred->xtmp    = xtmp;
1131e07b27eSBarry Smith   ierr = VecDestroy(&x);CHKERRQ(ierr);
1141e07b27eSBarry Smith   PetscFunctionReturn(0);
1151e07b27eSBarry Smith }
1161e07b27eSBarry Smith 
1171e07b27eSBarry Smith #undef __FUNCT__
1181e07b27eSBarry Smith #define __FUNCT__ "PCTelescopeMatCreate_default"
1191e07b27eSBarry Smith PetscErrorCode PCTelescopeMatCreate_default(PC pc,PC_Telescope sred,MatReuse reuse,Mat *A)
1201e07b27eSBarry Smith {
1211e07b27eSBarry Smith   PetscErrorCode ierr;
1221e07b27eSBarry Smith   MPI_Comm       comm,subcomm;
1231e07b27eSBarry Smith   Mat            Bred,B;
1241e07b27eSBarry Smith   PetscInt       nr,nc;
1251e07b27eSBarry Smith   IS             isrow,iscol;
1261e07b27eSBarry Smith   Mat            Blocal,*_Blocal;
1271e07b27eSBarry Smith 
1281e07b27eSBarry Smith   PetscFunctionBegin;
1291e07b27eSBarry Smith   ierr = PetscInfo(pc,"PCTelescope: updating the redundant preconditioned operator (default)\n");CHKERRQ(ierr);
1301e07b27eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
1311e07b27eSBarry Smith   subcomm = PetscSubcommChild(sred->psubcomm);
1321e07b27eSBarry Smith   ierr = PCGetOperators(pc,NULL,&B);CHKERRQ(ierr);
1331e07b27eSBarry Smith   ierr = MatGetSize(B,&nr,&nc);CHKERRQ(ierr);
1341e07b27eSBarry Smith   isrow = sred->isin;
1351e07b27eSBarry Smith   ierr = ISCreateStride(comm,nc,0,1,&iscol);CHKERRQ(ierr);
1361e07b27eSBarry Smith   ierr = MatGetSubMatrices(B,1,&isrow,&iscol,MAT_INITIAL_MATRIX,&_Blocal);CHKERRQ(ierr);
1371e07b27eSBarry Smith   Blocal = *_Blocal;
1381e07b27eSBarry Smith   ierr = PetscFree(_Blocal);CHKERRQ(ierr);
1391e07b27eSBarry Smith   Bred = NULL;
1401e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
1411e07b27eSBarry Smith     PetscInt mm;
1421e07b27eSBarry Smith 
1431e07b27eSBarry Smith     if (reuse != MAT_INITIAL_MATRIX) { Bred = *A; }
1441e07b27eSBarry Smith 
1451e07b27eSBarry Smith     ierr = MatGetSize(Blocal,&mm,NULL);CHKERRQ(ierr);
1461e07b27eSBarry Smith     ierr = MatCreateMPIMatConcatenateSeqMat(subcomm,Blocal,mm,reuse,&Bred);CHKERRQ(ierr);
1471e07b27eSBarry Smith   }
1481e07b27eSBarry Smith   *A = Bred;
1491e07b27eSBarry Smith   ierr = ISDestroy(&iscol);CHKERRQ(ierr);
1501e07b27eSBarry Smith   ierr = MatDestroy(&Blocal);CHKERRQ(ierr);
1511e07b27eSBarry Smith   PetscFunctionReturn(0);
1521e07b27eSBarry Smith }
1531e07b27eSBarry Smith 
1541e07b27eSBarry Smith #undef __FUNCT__
1551e07b27eSBarry Smith #define __FUNCT__ "PCTelescopeMatNullSpaceCreate_default"
1561e07b27eSBarry Smith PetscErrorCode PCTelescopeMatNullSpaceCreate_default(PC pc,PC_Telescope sred,Mat sub_mat)
1571e07b27eSBarry Smith {
1581e07b27eSBarry Smith   PetscErrorCode   ierr;
1591e07b27eSBarry Smith   MatNullSpace     nullspace,sub_nullspace;
1601e07b27eSBarry Smith   Mat              A,B;
1611e07b27eSBarry Smith   PetscBool        has_const;
162a947c41eSDave May   PetscInt         i,k,n = 0;
1631e07b27eSBarry Smith   const Vec        *vecs;
164c41e779fSDave May   Vec              *sub_vecs = NULL;
1651e07b27eSBarry Smith   MPI_Comm         subcomm;
1661e07b27eSBarry Smith 
1671e07b27eSBarry Smith   PetscFunctionBegin;
1681e07b27eSBarry Smith   ierr = PCGetOperators(pc,&A,&B);CHKERRQ(ierr);
1691e07b27eSBarry Smith   ierr = MatGetNullSpace(B,&nullspace);CHKERRQ(ierr);
170a947c41eSDave May   if (!nullspace) PetscFunctionReturn(0);
1711e07b27eSBarry Smith 
1721e07b27eSBarry Smith   ierr = PetscInfo(pc,"PCTelescope: generating nullspace (default)\n");CHKERRQ(ierr);
1731e07b27eSBarry Smith   subcomm = PetscSubcommChild(sred->psubcomm);
1741e07b27eSBarry Smith   ierr = MatNullSpaceGetVecs(nullspace,&has_const,&n,&vecs);CHKERRQ(ierr);
1751e07b27eSBarry Smith 
1761e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
177e3acf2f7SBarry Smith     if (n) {
178e3acf2f7SBarry Smith       ierr = VecDuplicateVecs(sred->xred,n,&sub_vecs);CHKERRQ(ierr);
1791e07b27eSBarry Smith     }
1801e07b27eSBarry Smith   }
1811e07b27eSBarry Smith 
1821e07b27eSBarry Smith   /* copy entries */
1831e07b27eSBarry Smith   for (k=0; k<n; k++) {
1841e07b27eSBarry Smith     const PetscScalar *x_array;
1851e07b27eSBarry Smith     PetscScalar       *LA_sub_vec;
18613c30530SDave May     PetscInt          st,ed;
1871e07b27eSBarry Smith 
1881e07b27eSBarry Smith     /* pull in vector x->xtmp */
1891e07b27eSBarry Smith     ierr = VecScatterBegin(sred->scatter,vecs[k],sred->xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1901e07b27eSBarry Smith     ierr = VecScatterEnd(sred->scatter,vecs[k],sred->xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19147856c66SBarry Smith     if (sub_vecs) {
1921e07b27eSBarry Smith       /* copy vector entires into xred */
1931e07b27eSBarry Smith       ierr = VecGetArrayRead(sred->xtmp,&x_array);CHKERRQ(ierr);
194ea2b237eSDave May       if (sub_vecs[k]) {
1951e07b27eSBarry Smith         ierr = VecGetOwnershipRange(sub_vecs[k],&st,&ed);CHKERRQ(ierr);
1961e07b27eSBarry Smith         ierr = VecGetArray(sub_vecs[k],&LA_sub_vec);CHKERRQ(ierr);
1971e07b27eSBarry Smith         for (i=0; i<ed-st; i++) {
1981e07b27eSBarry Smith           LA_sub_vec[i] = x_array[i];
1991e07b27eSBarry Smith         }
2001e07b27eSBarry Smith         ierr = VecRestoreArray(sub_vecs[k],&LA_sub_vec);CHKERRQ(ierr);
2011e07b27eSBarry Smith       }
2021e07b27eSBarry Smith       ierr = VecRestoreArrayRead(sred->xtmp,&x_array);CHKERRQ(ierr);
2031e07b27eSBarry Smith     }
20447856c66SBarry Smith   }
2051e07b27eSBarry Smith 
2061e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
2071e07b27eSBarry Smith     /* create new nullspace for redundant object */
2081e07b27eSBarry Smith     ierr = MatNullSpaceCreate(subcomm,has_const,n,sub_vecs,&sub_nullspace);CHKERRQ(ierr);
209120bdd93SDave May     sub_nullspace->remove = nullspace->remove;
210120bdd93SDave May     sub_nullspace->rmctx = nullspace->rmctx;
211120bdd93SDave May 
2121e07b27eSBarry Smith     /* attach redundant nullspace to Bred */
2131e07b27eSBarry Smith     ierr = MatSetNullSpace(sub_mat,sub_nullspace);CHKERRQ(ierr);
214e3acf2f7SBarry Smith     ierr = VecDestroyVecs(n,&sub_vecs);CHKERRQ(ierr);
2151e07b27eSBarry Smith   }
2161e07b27eSBarry Smith   PetscFunctionReturn(0);
2171e07b27eSBarry Smith }
2181e07b27eSBarry Smith 
2191e07b27eSBarry Smith #undef __FUNCT__
2201e07b27eSBarry Smith #define __FUNCT__ "PCView_Telescope"
2211e07b27eSBarry Smith static PetscErrorCode PCView_Telescope(PC pc,PetscViewer viewer)
2221e07b27eSBarry Smith {
2231e07b27eSBarry Smith   PC_Telescope     sred = (PC_Telescope)pc->data;
2241e07b27eSBarry Smith   PetscErrorCode   ierr;
2251e07b27eSBarry Smith   PetscBool        iascii,isstring;
2261e07b27eSBarry Smith   PetscViewer      subviewer;
2271e07b27eSBarry Smith 
2281e07b27eSBarry Smith   PetscFunctionBegin;
2291e07b27eSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
2301e07b27eSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr);
2311e07b27eSBarry Smith   if (iascii) {
2321e07b27eSBarry Smith     if (!sred->psubcomm) {
2331e07b27eSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Telescope: preconditioner not yet setup\n");CHKERRQ(ierr);
2341e07b27eSBarry Smith     } else {
2351e07b27eSBarry Smith       MPI_Comm    comm,subcomm;
2361e07b27eSBarry Smith       PetscMPIInt comm_size,subcomm_size;
2371e07b27eSBarry Smith       DM          dm,subdm;
2381e07b27eSBarry Smith 
2391e07b27eSBarry Smith       ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
2401e07b27eSBarry Smith       subdm = private_PCTelescopeGetSubDM(sred);
2411e07b27eSBarry Smith       comm = PetscSubcommParent(sred->psubcomm);
2421e07b27eSBarry Smith       subcomm = PetscSubcommChild(sred->psubcomm);
2431e07b27eSBarry Smith       ierr = MPI_Comm_size(comm,&comm_size);CHKERRQ(ierr);
2441e07b27eSBarry Smith       ierr = MPI_Comm_size(subcomm,&subcomm_size);CHKERRQ(ierr);
2451e07b27eSBarry Smith 
2461e07b27eSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Telescope: parent comm size reduction factor = %D\n",sred->redfactor);CHKERRQ(ierr);
2471e07b27eSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Telescope: comm_size = %d , subcomm_size = %d\n",(int)comm_size,(int)subcomm_size);CHKERRQ(ierr);
2481e07b27eSBarry Smith       ierr = PetscViewerGetSubViewer(viewer,subcomm,&subviewer);CHKERRQ(ierr);
2491e07b27eSBarry Smith       if (isActiveRank(sred->psubcomm)) {
2501e07b27eSBarry Smith         ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr);
2511e07b27eSBarry Smith 
2521e07b27eSBarry Smith         if (dm && sred->ignore_dm) {
2531e07b27eSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: ignoring DM\n");CHKERRQ(ierr);
2541e07b27eSBarry Smith         }
2557c5279cbSDave May         if (sred->ignore_kspcomputeoperators) {
2567c5279cbSDave May           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: ignoring KSPComputeOperators\n");CHKERRQ(ierr);
2577c5279cbSDave May         }
2581e07b27eSBarry Smith         switch (sred->sr_type) {
2591e07b27eSBarry Smith         case TELESCOPE_DEFAULT:
2601e07b27eSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: using default setup\n");CHKERRQ(ierr);
2611e07b27eSBarry Smith           break;
2621e07b27eSBarry Smith         case TELESCOPE_DMDA:
2631e07b27eSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: DMDA detected\n");CHKERRQ(ierr);
2641e07b27eSBarry Smith           ierr = DMView_DMDAShort(subdm,subviewer);CHKERRQ(ierr);
2651e07b27eSBarry Smith           break;
2661e07b27eSBarry Smith         case TELESCOPE_DMPLEX:
2671e07b27eSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: DMPLEX detected\n");CHKERRQ(ierr);
2681e07b27eSBarry Smith           break;
2691e07b27eSBarry Smith         }
2701e07b27eSBarry Smith 
2711e07b27eSBarry Smith         ierr = KSPView(sred->ksp,subviewer);CHKERRQ(ierr);
2721e07b27eSBarry Smith         ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr);
2731e07b27eSBarry Smith       }
2741e07b27eSBarry Smith       ierr = PetscViewerRestoreSubViewer(viewer,subcomm,&subviewer);CHKERRQ(ierr);
2751e07b27eSBarry Smith     }
2761e07b27eSBarry Smith   }
2771e07b27eSBarry Smith   PetscFunctionReturn(0);
2781e07b27eSBarry Smith }
2791e07b27eSBarry Smith 
2801e07b27eSBarry Smith #undef __FUNCT__
2811e07b27eSBarry Smith #define __FUNCT__ "PCSetUp_Telescope"
2821e07b27eSBarry Smith static PetscErrorCode PCSetUp_Telescope(PC pc)
2831e07b27eSBarry Smith {
2841e07b27eSBarry Smith   PC_Telescope      sred = (PC_Telescope)pc->data;
2851e07b27eSBarry Smith   PetscErrorCode    ierr;
286bd49479cSSatish Balay   MPI_Comm          comm,subcomm=0;
2871e07b27eSBarry Smith   PCTelescopeType   sr_type;
2881e07b27eSBarry Smith 
2891e07b27eSBarry Smith   PetscFunctionBegin;
2901e07b27eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
2911e07b27eSBarry Smith 
2921e07b27eSBarry Smith   /* subcomm definition */
2931e07b27eSBarry Smith   if (!pc->setupcalled) {
2941e07b27eSBarry Smith     if (!sred->psubcomm) {
2951e07b27eSBarry Smith       ierr = PetscSubcommCreate(comm,&sred->psubcomm);CHKERRQ(ierr);
2961e07b27eSBarry Smith       ierr = PetscSubcommSetNumber(sred->psubcomm,sred->redfactor);CHKERRQ(ierr);
2971e07b27eSBarry Smith       ierr = PetscSubcommSetType(sred->psubcomm,PETSC_SUBCOMM_INTERLACED);CHKERRQ(ierr);
2981e07b27eSBarry Smith       /* disable runtime switch of psubcomm type, e.g., '-psubcomm_type interlaced */
2991e07b27eSBarry Smith       /* ierr = PetscSubcommSetFromOptions(sred->psubcomm);CHKERRQ(ierr); */
3001e07b27eSBarry Smith       ierr = PetscLogObjectMemory((PetscObject)pc,sizeof(PetscSubcomm));CHKERRQ(ierr);
3011e07b27eSBarry Smith       /* create a new PC that processors in each subcomm have copy of */
3021e07b27eSBarry Smith     }
3031e07b27eSBarry Smith   }
3040f6f40a7SSatish Balay   subcomm = PetscSubcommChild(sred->psubcomm);
3051e07b27eSBarry Smith 
3061e07b27eSBarry Smith   /* internal KSP */
3071e07b27eSBarry Smith   if (!pc->setupcalled) {
3081e07b27eSBarry Smith     const char *prefix;
3091e07b27eSBarry Smith 
3101e07b27eSBarry Smith     if (isActiveRank(sred->psubcomm)) {
3111e07b27eSBarry Smith       ierr = KSPCreate(subcomm,&sred->ksp);CHKERRQ(ierr);
3121e07b27eSBarry Smith       ierr = KSPSetErrorIfNotConverged(sred->ksp,pc->erroriffailure);CHKERRQ(ierr);
3131e07b27eSBarry Smith       ierr = PetscObjectIncrementTabLevel((PetscObject)sred->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
3141e07b27eSBarry Smith       ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)sred->ksp);CHKERRQ(ierr);
3151e07b27eSBarry Smith       ierr = KSPSetType(sred->ksp,KSPPREONLY);CHKERRQ(ierr);
3161e07b27eSBarry Smith       ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
3171e07b27eSBarry Smith       ierr = KSPSetOptionsPrefix(sred->ksp,prefix);CHKERRQ(ierr);
3181e07b27eSBarry Smith       ierr = KSPAppendOptionsPrefix(sred->ksp,"telescope_");CHKERRQ(ierr);
3191e07b27eSBarry Smith     }
3201e07b27eSBarry Smith   }
3211e07b27eSBarry Smith   /* Determine type of setup/update */
3221e07b27eSBarry Smith   if (!pc->setupcalled) {
3231e07b27eSBarry Smith     PetscBool has_dm,same;
3241e07b27eSBarry Smith     DM        dm;
3251e07b27eSBarry Smith 
3261e07b27eSBarry Smith     sr_type = TELESCOPE_DEFAULT;
3271e07b27eSBarry Smith     has_dm = PETSC_FALSE;
3281e07b27eSBarry Smith     ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
3291e07b27eSBarry Smith     if (dm) { has_dm = PETSC_TRUE; }
3301e07b27eSBarry Smith     if (has_dm) {
3311e07b27eSBarry Smith       /* check for dmda */
3321e07b27eSBarry Smith       ierr = PetscObjectTypeCompare((PetscObject)dm,DMDA,&same);CHKERRQ(ierr);
3331e07b27eSBarry Smith       if (same) {
3341e07b27eSBarry Smith         ierr = PetscInfo(pc,"PCTelescope: found DMDA\n");CHKERRQ(ierr);
3351e07b27eSBarry Smith         sr_type = TELESCOPE_DMDA;
3361e07b27eSBarry Smith       }
3371e07b27eSBarry Smith       /* check for dmplex */
3381e07b27eSBarry Smith       ierr = PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&same);CHKERRQ(ierr);
3391e07b27eSBarry Smith       if (same) {
3401e07b27eSBarry Smith         PetscInfo(pc,"PCTelescope: found DMPLEX\n");
3411e07b27eSBarry Smith         sr_type = TELESCOPE_DMPLEX;
3421e07b27eSBarry Smith       }
3431e07b27eSBarry Smith     }
3441e07b27eSBarry Smith 
3451e07b27eSBarry Smith     if (sred->ignore_dm) {
3461e07b27eSBarry Smith       PetscInfo(pc,"PCTelescope: ignore DM\n");
3471e07b27eSBarry Smith       sr_type = TELESCOPE_DEFAULT;
3481e07b27eSBarry Smith     }
3491e07b27eSBarry Smith     sred->sr_type = sr_type;
3501e07b27eSBarry Smith   } else {
3511e07b27eSBarry Smith     sr_type = sred->sr_type;
3521e07b27eSBarry Smith   }
3531e07b27eSBarry Smith 
3541e07b27eSBarry Smith   /* set function pointers for repartition setup, matrix creation/update, matrix nullspace and reset functionality */
3551e07b27eSBarry Smith   switch (sr_type) {
3561e07b27eSBarry Smith   case TELESCOPE_DEFAULT:
3571e07b27eSBarry Smith     sred->pctelescope_setup_type              = PCTelescopeSetUp_default;
3581e07b27eSBarry Smith     sred->pctelescope_matcreate_type          = PCTelescopeMatCreate_default;
3591e07b27eSBarry Smith     sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_default;
3601e07b27eSBarry Smith     sred->pctelescope_reset_type              = NULL;
3611e07b27eSBarry Smith     break;
3621e07b27eSBarry Smith   case TELESCOPE_DMDA:
3631e07b27eSBarry Smith     pc->ops->apply                            = PCApply_Telescope_dmda;
364f650675bSDave May     pc->ops->applyrichardson                  = PCApplyRichardson_Telescope_dmda;
3651e07b27eSBarry Smith     sred->pctelescope_setup_type              = PCTelescopeSetUp_dmda;
3661e07b27eSBarry Smith     sred->pctelescope_matcreate_type          = PCTelescopeMatCreate_dmda;
3671e07b27eSBarry Smith     sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_dmda;
3681e07b27eSBarry Smith     sred->pctelescope_reset_type              = PCReset_Telescope_dmda;
3691e07b27eSBarry Smith     break;
3701e07b27eSBarry Smith   case TELESCOPE_DMPLEX: SETERRQ(comm,PETSC_ERR_SUP,"Supprt for DMPLEX is currently not available");
3711e07b27eSBarry Smith     break;
3721e07b27eSBarry Smith   default: SETERRQ(comm,PETSC_ERR_SUP,"Only supprt for repartitioning DMDA is provided");
3731e07b27eSBarry Smith     break;
3741e07b27eSBarry Smith   }
3751e07b27eSBarry Smith 
3761e07b27eSBarry Smith   /* setup */
3771e07b27eSBarry Smith   if (sred->pctelescope_setup_type) {
3781e07b27eSBarry Smith     ierr = sred->pctelescope_setup_type(pc,sred);CHKERRQ(ierr);
3791e07b27eSBarry Smith   }
3801e07b27eSBarry Smith   /* update */
3811e07b27eSBarry Smith   if (!pc->setupcalled) {
3821e07b27eSBarry Smith     if (sred->pctelescope_matcreate_type) {
3831e07b27eSBarry Smith       ierr = sred->pctelescope_matcreate_type(pc,sred,MAT_INITIAL_MATRIX,&sred->Bred);CHKERRQ(ierr);
3841e07b27eSBarry Smith     }
3851e07b27eSBarry Smith     if (sred->pctelescope_matnullspacecreate_type) {
3861e07b27eSBarry Smith       ierr = sred->pctelescope_matnullspacecreate_type(pc,sred,sred->Bred);CHKERRQ(ierr);
3871e07b27eSBarry Smith     }
3881e07b27eSBarry Smith   } else {
3891e07b27eSBarry Smith     if (sred->pctelescope_matcreate_type) {
3901e07b27eSBarry Smith       ierr = sred->pctelescope_matcreate_type(pc,sred,MAT_REUSE_MATRIX,&sred->Bred);CHKERRQ(ierr);
3911e07b27eSBarry Smith     }
3921e07b27eSBarry Smith   }
3931e07b27eSBarry Smith 
3941e07b27eSBarry Smith   /* common - no construction */
3951e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
3961e07b27eSBarry Smith     ierr = KSPSetOperators(sred->ksp,sred->Bred,sred->Bred);CHKERRQ(ierr);
3971e07b27eSBarry Smith     if (pc->setfromoptionscalled && !pc->setupcalled){
3981e07b27eSBarry Smith       ierr = KSPSetFromOptions(sred->ksp);CHKERRQ(ierr);
3991e07b27eSBarry Smith     }
4001e07b27eSBarry Smith   }
4011e07b27eSBarry Smith   PetscFunctionReturn(0);
4021e07b27eSBarry Smith }
4031e07b27eSBarry Smith 
4041e07b27eSBarry Smith #undef __FUNCT__
4051e07b27eSBarry Smith #define __FUNCT__ "PCApply_Telescope"
4061e07b27eSBarry Smith static PetscErrorCode PCApply_Telescope(PC pc,Vec x,Vec y)
4071e07b27eSBarry Smith {
4081e07b27eSBarry Smith   PC_Telescope      sred = (PC_Telescope)pc->data;
4091e07b27eSBarry Smith   PetscErrorCode    ierr;
4101e07b27eSBarry Smith   Vec               xtmp,xred,yred;
41113c30530SDave May   PetscInt          i,st,ed;
4121e07b27eSBarry Smith   VecScatter        scatter;
4131e07b27eSBarry Smith   PetscScalar       *array;
4141e07b27eSBarry Smith   const PetscScalar *x_array;
4151e07b27eSBarry Smith 
4161e07b27eSBarry Smith   PetscFunctionBegin;
4171e07b27eSBarry Smith   xtmp    = sred->xtmp;
4181e07b27eSBarry Smith   scatter = sred->scatter;
4191e07b27eSBarry Smith   xred    = sred->xred;
4201e07b27eSBarry Smith   yred    = sred->yred;
4211e07b27eSBarry Smith 
4221e07b27eSBarry Smith   /* pull in vector x->xtmp */
4231e07b27eSBarry Smith   ierr = VecScatterBegin(scatter,x,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4241e07b27eSBarry Smith   ierr = VecScatterEnd(scatter,x,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4251e07b27eSBarry Smith 
4261e07b27eSBarry Smith   /* copy vector entires into xred */
4271e07b27eSBarry Smith   ierr = VecGetArrayRead(xtmp,&x_array);CHKERRQ(ierr);
4281e07b27eSBarry Smith   if (xred) {
4291e07b27eSBarry Smith     PetscScalar *LA_xred;
4301e07b27eSBarry Smith     ierr = VecGetOwnershipRange(xred,&st,&ed);CHKERRQ(ierr);
4311e07b27eSBarry Smith     ierr = VecGetArray(xred,&LA_xred);CHKERRQ(ierr);
4321e07b27eSBarry Smith     for (i=0; i<ed-st; i++) {
4331e07b27eSBarry Smith       LA_xred[i] = x_array[i];
4341e07b27eSBarry Smith     }
4351e07b27eSBarry Smith     ierr = VecRestoreArray(xred,&LA_xred);CHKERRQ(ierr);
4361e07b27eSBarry Smith   }
4371e07b27eSBarry Smith   ierr = VecRestoreArrayRead(xtmp,&x_array);CHKERRQ(ierr);
4381e07b27eSBarry Smith   /* solve */
4391e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
4401e07b27eSBarry Smith     ierr = KSPSolve(sred->ksp,xred,yred);CHKERRQ(ierr);
4411e07b27eSBarry Smith   }
4421e07b27eSBarry Smith   /* return vector */
4431e07b27eSBarry Smith   ierr = VecGetArray(xtmp,&array);CHKERRQ(ierr);
4441e07b27eSBarry Smith   if (yred) {
4451e07b27eSBarry Smith     const PetscScalar *LA_yred;
4461e07b27eSBarry Smith     ierr = VecGetOwnershipRange(yred,&st,&ed);CHKERRQ(ierr);
4471e07b27eSBarry Smith     ierr = VecGetArrayRead(yred,&LA_yred);CHKERRQ(ierr);
4481e07b27eSBarry Smith     for (i=0; i<ed-st; i++) {
4491e07b27eSBarry Smith       array[i] = LA_yred[i];
4501e07b27eSBarry Smith     }
4511e07b27eSBarry Smith     ierr = VecRestoreArrayRead(yred,&LA_yred);CHKERRQ(ierr);
4521e07b27eSBarry Smith   }
4531e07b27eSBarry Smith   ierr = VecRestoreArray(xtmp,&array);CHKERRQ(ierr);
4541e07b27eSBarry Smith   ierr = VecScatterBegin(scatter,xtmp,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4551e07b27eSBarry Smith   ierr = VecScatterEnd(scatter,xtmp,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4561e07b27eSBarry Smith   PetscFunctionReturn(0);
4571e07b27eSBarry Smith }
4581e07b27eSBarry Smith 
4591e07b27eSBarry Smith #undef __FUNCT__
460f650675bSDave May #define __FUNCT__ "PCApplyRichardson_Telescope"
461f650675bSDave 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)
462f650675bSDave May {
463f650675bSDave May   PC_Telescope      sred = (PC_Telescope)pc->data;
464f650675bSDave May   PetscErrorCode    ierr;
465a1d91a28SDave May   Vec               xtmp,yred;
466f650675bSDave May   PetscInt          i,st,ed;
467f650675bSDave May   VecScatter        scatter;
468f650675bSDave May   const PetscScalar *x_array;
469f650675bSDave May   PetscBool         default_init_guess_value;
470f650675bSDave May 
471f650675bSDave May   PetscFunctionBegin;
472f650675bSDave May   xtmp    = sred->xtmp;
473f650675bSDave May   scatter = sred->scatter;
474f650675bSDave May   yred    = sred->yred;
475f650675bSDave May 
476f650675bSDave May   if (its > 1) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCApplyRichardson_Telescope only supports max_it = 1");
477f650675bSDave May   *reason = (PCRichardsonConvergedReason)0;
478f650675bSDave May 
479f650675bSDave May   if (!zeroguess) {
480f650675bSDave May     ierr = PetscInfo(pc,"PCTelescope: Scattering y for non-zero initial guess\n");CHKERRQ(ierr);
481f650675bSDave May     /* pull in vector y->xtmp */
482f650675bSDave May     ierr = VecScatterBegin(scatter,y,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
483f650675bSDave May     ierr = VecScatterEnd(scatter,y,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
484f650675bSDave May 
485f650675bSDave May     /* copy vector entires into xred */
486f650675bSDave May     ierr = VecGetArrayRead(xtmp,&x_array);CHKERRQ(ierr);
487f650675bSDave May     if (yred) {
488f650675bSDave May       PetscScalar *LA_yred;
489f650675bSDave May       ierr = VecGetOwnershipRange(yred,&st,&ed);CHKERRQ(ierr);
490f650675bSDave May       ierr = VecGetArray(yred,&LA_yred);CHKERRQ(ierr);
491f650675bSDave May       for (i=0; i<ed-st; i++) {
492f650675bSDave May         LA_yred[i] = x_array[i];
493f650675bSDave May       }
494f650675bSDave May       ierr = VecRestoreArray(yred,&LA_yred);CHKERRQ(ierr);
495f650675bSDave May     }
496f650675bSDave May     ierr = VecRestoreArrayRead(xtmp,&x_array);CHKERRQ(ierr);
497f650675bSDave May   }
498f650675bSDave May 
499f650675bSDave May   if (isActiveRank(sred->psubcomm)) {
500f650675bSDave May     ierr = KSPGetInitialGuessNonzero(sred->ksp,&default_init_guess_value);CHKERRQ(ierr);
501f650675bSDave May     if (!zeroguess) ierr = KSPSetInitialGuessNonzero(sred->ksp,PETSC_TRUE);CHKERRQ(ierr);
502f650675bSDave May   }
503f650675bSDave May 
504f650675bSDave May   ierr = PCApply_Telescope(pc,x,y);CHKERRQ(ierr);
505f650675bSDave May 
506f650675bSDave May   if (isActiveRank(sred->psubcomm)) {
507f650675bSDave May     ierr = KSPSetInitialGuessNonzero(sred->ksp,default_init_guess_value);CHKERRQ(ierr);
508f650675bSDave May   }
509f650675bSDave May 
510f650675bSDave May   if (!*reason) *reason = PCRICHARDSON_CONVERGED_ITS;
511f650675bSDave May   *outits = 1;
512f650675bSDave May   PetscFunctionReturn(0);
513f650675bSDave May }
514f650675bSDave May 
515f650675bSDave May #undef __FUNCT__
5161e07b27eSBarry Smith #define __FUNCT__ "PCReset_Telescope"
5171e07b27eSBarry Smith static PetscErrorCode PCReset_Telescope(PC pc)
5181e07b27eSBarry Smith {
5191e07b27eSBarry Smith   PC_Telescope   sred = (PC_Telescope)pc->data;
5201e07b27eSBarry Smith   PetscErrorCode ierr;
5211e07b27eSBarry Smith 
5221e07b27eSBarry Smith   ierr = ISDestroy(&sred->isin);CHKERRQ(ierr);
5231e07b27eSBarry Smith   ierr = VecScatterDestroy(&sred->scatter);CHKERRQ(ierr);
524e3acf2f7SBarry Smith   ierr = VecDestroy(&sred->xred);CHKERRQ(ierr);
525e3acf2f7SBarry Smith   ierr = VecDestroy(&sred->yred);CHKERRQ(ierr);
526e3acf2f7SBarry Smith   ierr = VecDestroy(&sred->xtmp);CHKERRQ(ierr);
527e3acf2f7SBarry Smith   ierr = MatDestroy(&sred->Bred);CHKERRQ(ierr);
528e3acf2f7SBarry Smith   ierr = KSPReset(sred->ksp);CHKERRQ(ierr);
5291e07b27eSBarry Smith   if (sred->pctelescope_reset_type) {
5301e07b27eSBarry Smith     ierr = sred->pctelescope_reset_type(pc);CHKERRQ(ierr);
5311e07b27eSBarry Smith   }
5321e07b27eSBarry Smith   PetscFunctionReturn(0);
5331e07b27eSBarry Smith }
5341e07b27eSBarry Smith 
5351e07b27eSBarry Smith #undef __FUNCT__
5361e07b27eSBarry Smith #define __FUNCT__ "PCDestroy_Telescope"
5371e07b27eSBarry Smith static PetscErrorCode PCDestroy_Telescope(PC pc)
5381e07b27eSBarry Smith {
5391e07b27eSBarry Smith   PC_Telescope     sred = (PC_Telescope)pc->data;
5401e07b27eSBarry Smith   PetscErrorCode   ierr;
5411e07b27eSBarry Smith 
5421e07b27eSBarry Smith   PetscFunctionBegin;
5431e07b27eSBarry Smith   ierr = PCReset_Telescope(pc);CHKERRQ(ierr);
544e3acf2f7SBarry Smith   ierr = KSPDestroy(&sred->ksp);CHKERRQ(ierr);
5451e07b27eSBarry Smith   ierr = PetscSubcommDestroy(&sred->psubcomm);CHKERRQ(ierr);
546e3acf2f7SBarry Smith   ierr = PetscFree(sred->dm_ctx);CHKERRQ(ierr);
547e3acf2f7SBarry Smith   ierr = PetscFree(pc->data);CHKERRQ(ierr);
5481e07b27eSBarry Smith   PetscFunctionReturn(0);
5491e07b27eSBarry Smith }
5501e07b27eSBarry Smith 
5511e07b27eSBarry Smith #undef __FUNCT__
5521e07b27eSBarry Smith #define __FUNCT__ "PCSetFromOptions_Telescope"
5534416b707SBarry Smith static PetscErrorCode PCSetFromOptions_Telescope(PetscOptionItems *PetscOptionsObject,PC pc)
5541e07b27eSBarry Smith {
5551e07b27eSBarry Smith   PC_Telescope     sred = (PC_Telescope)pc->data;
5561e07b27eSBarry Smith   PetscErrorCode   ierr;
5571e07b27eSBarry Smith   MPI_Comm         comm;
5581e07b27eSBarry Smith   PetscMPIInt      size;
5591e07b27eSBarry Smith 
5601e07b27eSBarry Smith   PetscFunctionBegin;
5611e07b27eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
5621e07b27eSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
5631e07b27eSBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"Telescope options");CHKERRQ(ierr);
5641e07b27eSBarry Smith   ierr = PetscOptionsInt("-pc_telescope_reduction_factor","Factor to reduce comm size by","PCTelescopeSetReductionFactor",sred->redfactor,&sred->redfactor,0);CHKERRQ(ierr);
5651e07b27eSBarry Smith   if (sred->redfactor > size) SETERRQ(comm,PETSC_ERR_ARG_WRONG,"-pc_telescope_reduction_factor <= comm size");
5661e07b27eSBarry Smith   ierr = PetscOptionsBool("-pc_telescope_ignore_dm","Ignore any DM attached to the PC","PCTelescopeSetIgnoreDM",sred->ignore_dm,&sred->ignore_dm,0);CHKERRQ(ierr);
5677c5279cbSDave May   ierr = PetscOptionsBool("-pc_telescope_ignore_kspcomputeoperators","Ignore method used to compute A","PCTelescopeSetIgnoreKSPComputeOperators",sred->ignore_kspcomputeoperators,&sred->ignore_kspcomputeoperators,0);CHKERRQ(ierr);
5681e07b27eSBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
5691e07b27eSBarry Smith   PetscFunctionReturn(0);
5701e07b27eSBarry Smith }
5711e07b27eSBarry Smith 
5721e07b27eSBarry Smith /* PC simplementation specific API's */
5731e07b27eSBarry Smith 
5741e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetKSP_Telescope(PC pc,KSP *ksp)
5751e07b27eSBarry Smith {
5761e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
577bd49479cSSatish Balay   PetscFunctionBegin;
5781e07b27eSBarry Smith   if (ksp) *ksp = red->ksp;
579bd49479cSSatish Balay   PetscFunctionReturn(0);
5801e07b27eSBarry Smith }
5811e07b27eSBarry Smith 
5821e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetReductionFactor_Telescope(PC pc,PetscInt *fact)
5831e07b27eSBarry Smith {
5841e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
585bd49479cSSatish Balay   PetscFunctionBegin;
5861e07b27eSBarry Smith   if (fact) *fact = red->redfactor;
587bd49479cSSatish Balay   PetscFunctionReturn(0);
5881e07b27eSBarry Smith }
5891e07b27eSBarry Smith 
5901e07b27eSBarry Smith static PetscErrorCode PCTelescopeSetReductionFactor_Telescope(PC pc,PetscInt fact)
5911e07b27eSBarry Smith {
5921e07b27eSBarry Smith   PC_Telescope     red = (PC_Telescope)pc->data;
5931e07b27eSBarry Smith   PetscMPIInt      size;
5941e07b27eSBarry Smith   PetscErrorCode   ierr;
5951e07b27eSBarry Smith 
596bd49479cSSatish Balay   PetscFunctionBegin;
5971e07b27eSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
5981e07b27eSBarry Smith   if (fact <= 0) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Reduction factor of telescoping PC %D must be positive",fact);
5991e07b27eSBarry Smith   if (fact > size) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Reduction factor of telescoping PC %D must be <= comm.size",fact);
6001e07b27eSBarry Smith   red->redfactor = fact;
601bd49479cSSatish Balay   PetscFunctionReturn(0);
6021e07b27eSBarry Smith }
6031e07b27eSBarry Smith 
6041e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetIgnoreDM_Telescope(PC pc,PetscBool *v)
6051e07b27eSBarry Smith {
6061e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
607bd49479cSSatish Balay   PetscFunctionBegin;
6081e07b27eSBarry Smith   if (v) *v = red->ignore_dm;
609bd49479cSSatish Balay   PetscFunctionReturn(0);
6101e07b27eSBarry Smith }
6111e07b27eSBarry Smith static PetscErrorCode PCTelescopeSetIgnoreDM_Telescope(PC pc,PetscBool v)
6121e07b27eSBarry Smith {
6131e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
614bd49479cSSatish Balay   PetscFunctionBegin;
6151e07b27eSBarry Smith   red->ignore_dm = v;
616bd49479cSSatish Balay   PetscFunctionReturn(0);
6171e07b27eSBarry Smith }
6181e07b27eSBarry Smith 
6190ae7c45bSDave May static PetscErrorCode PCTelescopeGetIgnoreKSPComputeOperators_Telescope(PC pc,PetscBool *v)
6200ae7c45bSDave May {
6210ae7c45bSDave May   PC_Telescope red = (PC_Telescope)pc->data;
6220ae7c45bSDave May   PetscFunctionBegin;
6230ae7c45bSDave May   if (v) *v = red->ignore_kspcomputeoperators;
6240ae7c45bSDave May   PetscFunctionReturn(0);
6250ae7c45bSDave May }
6260ae7c45bSDave May static PetscErrorCode PCTelescopeSetIgnoreKSPComputeOperators_Telescope(PC pc,PetscBool v)
6270ae7c45bSDave May {
6280ae7c45bSDave May   PC_Telescope red = (PC_Telescope)pc->data;
6290ae7c45bSDave May   PetscFunctionBegin;
6300ae7c45bSDave May   red->ignore_kspcomputeoperators = v;
6310ae7c45bSDave May   PetscFunctionReturn(0);
6320ae7c45bSDave May }
6330ae7c45bSDave May 
6341e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetDM_Telescope(PC pc,DM *dm)
6351e07b27eSBarry Smith {
6361e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
637bd49479cSSatish Balay   PetscFunctionBegin;
6381e07b27eSBarry Smith   *dm = private_PCTelescopeGetSubDM(red);
639bd49479cSSatish Balay   PetscFunctionReturn(0);
6401e07b27eSBarry Smith }
6411e07b27eSBarry Smith 
6421e07b27eSBarry Smith /*@
6431e07b27eSBarry Smith  PCTelescopeGetKSP - Gets the KSP created by the telescoping PC.
6441e07b27eSBarry Smith 
6451e07b27eSBarry Smith  Not Collective
6461e07b27eSBarry Smith 
6471e07b27eSBarry Smith  Input Parameter:
6481e07b27eSBarry Smith  .  pc - the preconditioner context
6491e07b27eSBarry Smith 
6501e07b27eSBarry Smith  Output Parameter:
6511e07b27eSBarry Smith  .  subksp - the KSP defined the smaller set of processes
6521e07b27eSBarry Smith 
6531e07b27eSBarry Smith  Level: advanced
6541e07b27eSBarry Smith 
6551e07b27eSBarry Smith  .keywords: PC, telescopting solve
6561e07b27eSBarry Smith  @*/
6571e07b27eSBarry Smith PetscErrorCode PCTelescopeGetKSP(PC pc,KSP *subksp)
6581e07b27eSBarry Smith {
659bd49479cSSatish Balay   PetscErrorCode ierr;
660bd49479cSSatish Balay   PetscFunctionBegin;
661163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetKSP_C",(PC,KSP*),(pc,subksp));CHKERRQ(ierr);
662bd49479cSSatish Balay   PetscFunctionReturn(0);
6631e07b27eSBarry Smith }
6641e07b27eSBarry Smith 
6651e07b27eSBarry Smith /*@
6661e07b27eSBarry Smith  PCTelescopeGetReductionFactor - Gets the factor by which the original number of processes has been reduced by.
6671e07b27eSBarry Smith 
6681e07b27eSBarry Smith  Not Collective
6691e07b27eSBarry Smith 
6701e07b27eSBarry Smith  Input Parameter:
6711e07b27eSBarry Smith  .  pc - the preconditioner context
6721e07b27eSBarry Smith 
6731e07b27eSBarry Smith  Output Parameter:
6741e07b27eSBarry Smith  .  fact - the reduction factor
6751e07b27eSBarry Smith 
6761e07b27eSBarry Smith  Level: advanced
6771e07b27eSBarry Smith 
6781e07b27eSBarry Smith  .keywords: PC, telescoping solve
6791e07b27eSBarry Smith  @*/
6801e07b27eSBarry Smith PetscErrorCode PCTelescopeGetReductionFactor(PC pc,PetscInt *fact)
6811e07b27eSBarry Smith {
682bd49479cSSatish Balay   PetscErrorCode ierr;
683bd49479cSSatish Balay   PetscFunctionBegin;
684163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetReductionFactor_C",(PC,PetscInt*),(pc,fact));CHKERRQ(ierr);
685bd49479cSSatish Balay   PetscFunctionReturn(0);
6861e07b27eSBarry Smith }
6871e07b27eSBarry Smith 
6881e07b27eSBarry Smith /*@
6891e07b27eSBarry Smith  PCTelescopeSetReductionFactor - Sets the factor by which the original number of processes has been reduced by.
6901e07b27eSBarry Smith 
6911e07b27eSBarry Smith  Not Collective
6921e07b27eSBarry Smith 
6931e07b27eSBarry Smith  Input Parameter:
6941e07b27eSBarry Smith  .  pc - the preconditioner context
6951e07b27eSBarry Smith 
6961e07b27eSBarry Smith  Output Parameter:
6971e07b27eSBarry Smith  .  fact - the reduction factor
6981e07b27eSBarry Smith 
6991e07b27eSBarry Smith  Level: advanced
7001e07b27eSBarry Smith 
7011e07b27eSBarry Smith  .keywords: PC, telescoping solve
7021e07b27eSBarry Smith  @*/
7031e07b27eSBarry Smith PetscErrorCode PCTelescopeSetReductionFactor(PC pc,PetscInt fact)
7041e07b27eSBarry Smith {
705bd49479cSSatish Balay   PetscErrorCode ierr;
706bd49479cSSatish Balay   PetscFunctionBegin;
707bd49479cSSatish Balay   ierr = PetscTryMethod(pc,"PCTelescopeSetReductionFactor_C",(PC,PetscInt),(pc,fact));CHKERRQ(ierr);
708bd49479cSSatish Balay   PetscFunctionReturn(0);
7091e07b27eSBarry Smith }
7101e07b27eSBarry Smith 
7111e07b27eSBarry Smith /*@
7121e07b27eSBarry Smith  PCTelescopeGetIgnoreDM - Get the flag indicating if any DM attached to the PC will be used.
7131e07b27eSBarry Smith 
7141e07b27eSBarry Smith  Not Collective
7151e07b27eSBarry Smith 
7161e07b27eSBarry Smith  Input Parameter:
7171e07b27eSBarry Smith  .  pc - the preconditioner context
7181e07b27eSBarry Smith 
7191e07b27eSBarry Smith  Output Parameter:
7201e07b27eSBarry Smith  .  v - the flag
7211e07b27eSBarry Smith 
7221e07b27eSBarry Smith  Level: advanced
7231e07b27eSBarry Smith 
7241e07b27eSBarry Smith  .keywords: PC, telescoping solve
7251e07b27eSBarry Smith  @*/
7261e07b27eSBarry Smith PetscErrorCode PCTelescopeGetIgnoreDM(PC pc,PetscBool *v)
7271e07b27eSBarry Smith {
728bd49479cSSatish Balay   PetscErrorCode ierr;
729bd49479cSSatish Balay   PetscFunctionBegin;
730163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetIgnoreDM_C",(PC,PetscBool*),(pc,v));CHKERRQ(ierr);
731bd49479cSSatish Balay   PetscFunctionReturn(0);
7321e07b27eSBarry Smith }
7331e07b27eSBarry Smith 
7341e07b27eSBarry Smith /*@
7351e07b27eSBarry Smith  PCTelescopeSetIgnoreDM - Set a flag to ignore any DM attached to the PC.
7361e07b27eSBarry Smith 
7371e07b27eSBarry Smith  Not Collective
7381e07b27eSBarry Smith 
7391e07b27eSBarry Smith  Input Parameter:
7401e07b27eSBarry Smith  .  pc - the preconditioner context
7411e07b27eSBarry Smith 
7421e07b27eSBarry Smith  Output Parameter:
7431e07b27eSBarry Smith  .  v - Use PETSC_TRUE to ignore any DM
7441e07b27eSBarry Smith 
7451e07b27eSBarry Smith  Level: advanced
7461e07b27eSBarry Smith 
7471e07b27eSBarry Smith  .keywords: PC, telescoping solve
7481e07b27eSBarry Smith  @*/
749bfd6bcc6SSatish Balay PetscErrorCode PCTelescopeSetIgnoreDM(PC pc,PetscBool v)
7501e07b27eSBarry Smith {
751bd49479cSSatish Balay   PetscErrorCode ierr;
752bd49479cSSatish Balay   PetscFunctionBegin;
753bd49479cSSatish Balay   ierr = PetscTryMethod(pc,"PCTelescopeSetIgnoreDM_C",(PC,PetscBool),(pc,v));CHKERRQ(ierr);
754bd49479cSSatish Balay   PetscFunctionReturn(0);
7551e07b27eSBarry Smith }
7561e07b27eSBarry Smith 
7571e07b27eSBarry Smith /*@
7580ae7c45bSDave May  PCTelescopeGetIgnoreKSPComputeOperators - Get the flag indicating if KSPComputeOperators will be used.
7590ae7c45bSDave May 
7600ae7c45bSDave May  Not Collective
7610ae7c45bSDave May 
7620ae7c45bSDave May  Input Parameter:
7630ae7c45bSDave May  .  pc - the preconditioner context
7640ae7c45bSDave May 
7650ae7c45bSDave May  Output Parameter:
7660ae7c45bSDave May  .  v - the flag
7670ae7c45bSDave May 
7680ae7c45bSDave May  Level: advanced
7690ae7c45bSDave May 
7700ae7c45bSDave May  .keywords: PC, telescoping solve
7710ae7c45bSDave May  @*/
7720ae7c45bSDave May PetscErrorCode PCTelescopeGetIgnoreKSPComputeOperators(PC pc,PetscBool *v)
7730ae7c45bSDave May {
7740ae7c45bSDave May   PetscErrorCode ierr;
7750ae7c45bSDave May   PetscFunctionBegin;
776163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetIgnoreKSPComputeOperators_C",(PC,PetscBool*),(pc,v));CHKERRQ(ierr);
7770ae7c45bSDave May   PetscFunctionReturn(0);
7780ae7c45bSDave May }
7790ae7c45bSDave May 
7800ae7c45bSDave May /*@
7810ae7c45bSDave May  PCTelescopeSetIgnoreKSPComputeOperators - Set a flag to ignore KSPComputeOperators.
7820ae7c45bSDave May 
7830ae7c45bSDave May  Not Collective
7840ae7c45bSDave May 
7850ae7c45bSDave May  Input Parameter:
7860ae7c45bSDave May  .  pc - the preconditioner context
7870ae7c45bSDave May 
7880ae7c45bSDave May  Output Parameter:
789a954d8f4SDave May  .  v - Use PETSC_TRUE to ignore the method (if defined) set via KSPSetComputeOperators on pc
7900ae7c45bSDave May 
7910ae7c45bSDave May  Level: advanced
7920ae7c45bSDave May 
7930ae7c45bSDave May  .keywords: PC, telescoping solve
7940ae7c45bSDave May  @*/
7950ae7c45bSDave May PetscErrorCode PCTelescopeSetIgnoreKSPComputeOperators(PC pc,PetscBool v)
7960ae7c45bSDave May {
7970ae7c45bSDave May   PetscErrorCode ierr;
7980ae7c45bSDave May   PetscFunctionBegin;
7990ae7c45bSDave May   ierr = PetscTryMethod(pc,"PCTelescopeSetIgnoreKSPComputeOperators_C",(PC,PetscBool),(pc,v));CHKERRQ(ierr);
8000ae7c45bSDave May   PetscFunctionReturn(0);
8010ae7c45bSDave May }
8020ae7c45bSDave May 
8030ae7c45bSDave May /*@
8041e07b27eSBarry Smith  PCTelescopeGetDM - Get the re-partitioned DM attached to the sub KSP.
8051e07b27eSBarry Smith 
8061e07b27eSBarry Smith  Not Collective
8071e07b27eSBarry Smith 
8081e07b27eSBarry Smith  Input Parameter:
8091e07b27eSBarry Smith  .  pc - the preconditioner context
8101e07b27eSBarry Smith 
8111e07b27eSBarry Smith  Output Parameter:
8121e07b27eSBarry Smith  .  subdm - The re-partitioned DM
8131e07b27eSBarry Smith 
8141e07b27eSBarry Smith  Level: advanced
8151e07b27eSBarry Smith 
8161e07b27eSBarry Smith  .keywords: PC, telescoping solve
8171e07b27eSBarry Smith  @*/
8181e07b27eSBarry Smith PetscErrorCode PCTelescopeGetDM(PC pc,DM *subdm)
8191e07b27eSBarry Smith {
820bd49479cSSatish Balay   PetscErrorCode ierr;
821bd49479cSSatish Balay   PetscFunctionBegin;
822163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetDM_C",(PC,DM*),(pc,subdm));CHKERRQ(ierr);
823bd49479cSSatish Balay   PetscFunctionReturn(0);
8241e07b27eSBarry Smith }
8251e07b27eSBarry Smith 
8261e07b27eSBarry Smith /* -------------------------------------------------------------------------------------*/
8271e07b27eSBarry Smith /*MC
8281e07b27eSBarry Smith    PCTELESCOPE - Runs a KSP solver on a sub-group of processors. MPI processes not in the sub-communicator are idle during the solve.
8291e07b27eSBarry Smith 
8301e07b27eSBarry Smith    Options Database:
8311e07b27eSBarry Smith +  -pc_telescope_reduction_factor <n> - factor to use communicator size by, for example if you are using 64 MPI processes and
8321e07b27eSBarry Smith    use an n of 4, the new sub-communicator will be 4 defined with 64/4 processes
8331e07b27eSBarry Smith -  -pc_telescope_ignore_dm <false> - flag to indicate whether an attached DM should be ignored
8341e07b27eSBarry Smith 
8351e07b27eSBarry Smith    Level: advanced
8361e07b27eSBarry Smith 
8371e07b27eSBarry Smith    Notes:
8386fc41876SBarry Smith    The preconditioner is deemed telescopic as it only calls KSPSolve() on a single
8396fc41876SBarry Smith    sub-communicator in contrast with PCREDUNDANT which calls KSPSolve() on N sub-communicators.
8406fc41876SBarry Smith    This means there will be MPI processes within c, which will be idle during the application of this preconditioner.
8416fc41876SBarry Smith 
8421e07b27eSBarry Smith    The default KSP is PREONLY. If a DM is attached to the PC, it is re-partitioned on the sub-communicator.
8431e07b27eSBarry Smith    Both the B mat operator and the right hand side vector are permuted into the new DOF ordering defined by the re-partitioned DM.
8441e07b27eSBarry Smith    Currently only support for re-partitioning a DMDA is provided.
8451e07b27eSBarry Smith    Any nullspace attached to the original Bmat operator are extracted, re-partitioned and set on the repartitioned Bmat operator.
8461e07b27eSBarry Smith    KSPSetComputeOperators() is not propagated to the sub KSP.
8471e07b27eSBarry Smith    Currently there is no support for the flag -pc_use_amat
8481e07b27eSBarry Smith 
8496fc41876SBarry Smith    Assuming that the parent preconditioner (PC) is defined on a communicator c, this implementation
8506fc41876SBarry Smith    creates a child sub-communicator (c') containing less MPI processes than the original parent preconditioner (PC).
8516fc41876SBarry Smith 
8526fc41876SBarry Smith   Developer Notes:
8536fc41876SBarry Smith    During PCSetup, the B operator is scattered onto c'.
8546fc41876SBarry Smith    Within PCApply, the RHS vector (x) is scattered into a redundant vector, xred (defined on c').
8556fc41876SBarry Smith    Then KSPSolve() is executed on the c' communicator.
8566fc41876SBarry Smith 
8576fc41876SBarry Smith    The communicator used within the telescoping preconditioner is defined by a PetscSubcomm using the INTERLACED
8586fc41876SBarry Smith    creation routine. We run the sub KSP on only the ranks within the communicator which have a color equal to zero.
8596fc41876SBarry Smith 
8606fc41876SBarry Smith    The telescoping preconditioner is aware of nullspaces which are attached to the only B operator.
8616fc41876SBarry Smith    In case where B has a n nullspace attached, these nullspaces vectors are extract from B and mapped into
8626fc41876SBarry Smith    a new nullspace (defined on the sub-communicator) which is attached to B' (the B operator which was scattered to c')
8636fc41876SBarry Smith 
8646fc41876SBarry Smith    The telescoping preconditioner is aware of an attached DM. In the event that the DM is of type DMDA (2D or 3D -
8656fc41876SBarry 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
8666fc41876SBarry Smith    is attached the sub KSPSolve(). The design of telescope is such that it should be possible to extend support
8676fc41876SBarry Smith    for re-partitioning other DM's (e.g. DMPLEX). The user can supply a flag to ignore attached DMs.
8686fc41876SBarry Smith 
8696fc41876SBarry Smith    By default, B' is defined by simply fusing rows from different MPI processes
8706fc41876SBarry Smith 
8716fc41876SBarry Smith    When a DMDA is attached to the parent preconditioner, B' is defined by: (i) performing a symmetric permuting of B
8726fc41876SBarry Smith    into the ordering defined by the DMDA on c', (ii) extracting the local chunks via MatGetSubMatrices(), (iii) fusing the
8736fc41876SBarry Smith    locally (sequential) matrices defined on the ranks common to c and c' into B' using MatCreateMPIMatConcatenateSeqMat()
8746fc41876SBarry Smith 
8756fc41876SBarry Smith    Limitations/improvements
8766fc41876SBarry Smith    VecPlaceArray could be used within PCApply() to improve efficiency and reduce memory usage.
8776fc41876SBarry Smith 
8786fc41876SBarry Smith    The symmetric permutation used when a DMDA is encountered is performed via explicitly assmbleming a permutation matrix P,
8796fc41876SBarry Smith    and performing P^T.A.P. Possibly it might be more efficient to use MatPermute(). I opted to use P^T.A.P as it appears
8806fc41876SBarry Smith    VecPermute() does not supported for the use case required here. By computing P, I can permute both the operator and RHS in a
8816fc41876SBarry Smith    consistent manner.
8826fc41876SBarry Smith 
8836fc41876SBarry Smith    Mapping of vectors is performed this way
8846fc41876SBarry Smith    Suppose the parent comm size was 4, and we set a reduction factor of 2, thus would give a comm size on c' of 2.
8856fc41876SBarry Smith    Using the interlaced creation routine, the ranks in c with color = 0, will be rank 0 and 2.
8866fc41876SBarry Smith    We perform the scatter to the sub-comm in the following way,
8876fc41876SBarry Smith    [1] Given a vector x defined on comm c
8886fc41876SBarry Smith 
8896fc41876SBarry Smith    rank(c) : _________ 0 ______  ________ 1 _______  ________ 2 _____________ ___________ 3 __________
8906fc41876SBarry 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]
8916fc41876SBarry Smith 
8926fc41876SBarry Smith    scatter to xtmp defined also on comm c so that we have the following values
8936fc41876SBarry Smith 
8946fc41876SBarry Smith    rank(c) : ___________________ 0 ________________  _1_  ______________________ 2 _______________________  __3_
8956fc41876SBarry 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] [  ]
8966fc41876SBarry Smith 
8976fc41876SBarry Smith    The entries on rank 1 and 3 (ranks which do not have a color = 0 in c') have no values
8986fc41876SBarry Smith 
8996fc41876SBarry Smith 
9006fc41876SBarry 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'.
9016fc41876SBarry Smith    Ranks 0 and 2 are the only ranks in the subcomm which have a color = 0.
9026fc41876SBarry Smith 
9036fc41876SBarry Smith     rank(c') : ___________________ 0 _______________  ______________________ 1 _____________________
9046fc41876SBarry 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]
9056fc41876SBarry Smith 
9061e07b27eSBarry Smith 
9071e07b27eSBarry Smith   Contributed by Dave May
9081e07b27eSBarry Smith 
9096fc41876SBarry Smith .seealso:  PCTelescopeGetKSP(), PCTelescopeGetDM(), PCTelescopeGetReductionFactor(), PCTelescopeSetReductionFactor(), PCTelescopeGetIgnoreDM(), PCTelescopeSetIgnoreDM(), PCREDUNDANT
9101e07b27eSBarry Smith M*/
9111e07b27eSBarry Smith #undef __FUNCT__
9121e07b27eSBarry Smith #define __FUNCT__ "PCCreate_Telescope"
9131e07b27eSBarry Smith PETSC_EXTERN PetscErrorCode PCCreate_Telescope(PC pc)
9141e07b27eSBarry Smith {
9151e07b27eSBarry Smith   PetscErrorCode       ierr;
9161e07b27eSBarry Smith   struct _PC_Telescope *sred;
9171e07b27eSBarry Smith 
9181e07b27eSBarry Smith   PetscFunctionBegin;
9191e07b27eSBarry Smith   ierr = PetscNewLog(pc,&sred);CHKERRQ(ierr);
9201e07b27eSBarry Smith   sred->redfactor      = 1;
9211e07b27eSBarry Smith   sred->ignore_dm      = PETSC_FALSE;
9227c5279cbSDave May   sred->ignore_kspcomputeoperators = PETSC_FALSE;
9231e07b27eSBarry Smith   pc->data             = (void*)sred;
9241e07b27eSBarry Smith 
9251e07b27eSBarry Smith   pc->ops->apply           = PCApply_Telescope;
9261e07b27eSBarry Smith   pc->ops->applytranspose  = NULL;
927f650675bSDave May   pc->ops->applyrichardson = PCApplyRichardson_Telescope;
9281e07b27eSBarry Smith   pc->ops->setup           = PCSetUp_Telescope;
9291e07b27eSBarry Smith   pc->ops->destroy         = PCDestroy_Telescope;
9301e07b27eSBarry Smith   pc->ops->reset           = PCReset_Telescope;
9311e07b27eSBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_Telescope;
9321e07b27eSBarry Smith   pc->ops->view            = PCView_Telescope;
9331e07b27eSBarry Smith 
9341e07b27eSBarry Smith   sred->pctelescope_setup_type              = PCTelescopeSetUp_default;
9351e07b27eSBarry Smith   sred->pctelescope_matcreate_type          = PCTelescopeMatCreate_default;
9361e07b27eSBarry Smith   sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_default;
9371e07b27eSBarry Smith   sred->pctelescope_reset_type              = NULL;
9381e07b27eSBarry Smith 
9391e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetKSP_C",PCTelescopeGetKSP_Telescope);CHKERRQ(ierr);
9401e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetReductionFactor_C",PCTelescopeGetReductionFactor_Telescope);CHKERRQ(ierr);
9411e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetReductionFactor_C",PCTelescopeSetReductionFactor_Telescope);CHKERRQ(ierr);
9421e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetIgnoreDM_C",PCTelescopeGetIgnoreDM_Telescope);CHKERRQ(ierr);
9431e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetIgnoreDM_C",PCTelescopeSetIgnoreDM_Telescope);CHKERRQ(ierr);
9440ae7c45bSDave May   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetIgnoreKSPComputeOperators_C",PCTelescopeGetIgnoreKSPComputeOperators_Telescope);CHKERRQ(ierr);
9450ae7c45bSDave May   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetIgnoreKSPComputeOperators_C",PCTelescopeSetIgnoreKSPComputeOperators_Telescope);CHKERRQ(ierr);
9461e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetDM_C",PCTelescopeGetDM_Telescope);CHKERRQ(ierr);
9471e07b27eSBarry Smith   PetscFunctionReturn(0);
9481e07b27eSBarry Smith }
949