xref: /petsc/src/ksp/pc/impls/telescope/telescope.c (revision bf00f5894b9a43e0d7290f7d5c9387b3432f8cd5)
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 
8*bf00f589SPatrick Sanan static PetscBool  cited = PETSC_FALSE;
9*bf00f589SPatrick Sanan static const char citation[] =
10*bf00f589SPatrick Sanan "@inproceedings{MaySananRuppKnepleySmith2016,\n"
11*bf00f589SPatrick Sanan "  title     = {Extreme-Scale Multigrid Components within PETSc},\n"
12*bf00f589SPatrick Sanan "  author    = {Dave A. May and Patrick Sanan and Karl Rupp and Matthew G. Knepley and Barry F. Smith},\n"
13*bf00f589SPatrick Sanan "  booktitle = {Proceedings of the Platform for Advanced Scientific Computing Conference},\n"
14*bf00f589SPatrick Sanan "  series    = {PASC '16},\n"
15*bf00f589SPatrick Sanan "  isbn      = {978-1-4503-4126-4},\n"
16*bf00f589SPatrick Sanan "  location  = {Lausanne, Switzerland},\n"
17*bf00f589SPatrick Sanan "  pages     = {5:1--5:12},\n"
18*bf00f589SPatrick Sanan "  articleno = {5},\n"
19*bf00f589SPatrick Sanan "  numpages  = {12},\n"
20*bf00f589SPatrick Sanan "  url       = {http://doi.acm.org/10.1145/2929908.2929913},\n"
21*bf00f589SPatrick Sanan "  doi       = {10.1145/2929908.2929913},\n"
22*bf00f589SPatrick Sanan "  acmid     = {2929913},\n"
23*bf00f589SPatrick Sanan "  publisher = {ACM},\n"
24*bf00f589SPatrick Sanan "  address   = {New York, NY, USA},\n"
25*bf00f589SPatrick Sanan "  keywords  = {GPU, HPC, agglomeration, coarse-level solver, multigrid, parallel computing, preconditioning},\n"
26*bf00f589SPatrick Sanan "  year      = {2016}\n"
27*bf00f589SPatrick Sanan "}\n";
28*bf00f589SPatrick Sanan 
291e07b27eSBarry Smith /*
301e07b27eSBarry Smith  PCTelescopeSetUp_default()
311e07b27eSBarry Smith  PCTelescopeMatCreate_default()
321e07b27eSBarry Smith 
331e07b27eSBarry Smith  default
341e07b27eSBarry Smith 
351e07b27eSBarry Smith  // scatter in
361e07b27eSBarry Smith  x(comm) -> xtmp(comm)
371e07b27eSBarry Smith 
381e07b27eSBarry Smith  xred(subcomm) <- xtmp
391e07b27eSBarry Smith  yred(subcomm)
401e07b27eSBarry Smith 
411e07b27eSBarry Smith  yred(subcomm) --> xtmp
421e07b27eSBarry Smith 
431e07b27eSBarry Smith  // scatter out
441e07b27eSBarry Smith  xtmp(comm) -> y(comm)
451e07b27eSBarry Smith */
461e07b27eSBarry Smith 
471e07b27eSBarry Smith PetscBool isActiveRank(PetscSubcomm scomm)
481e07b27eSBarry Smith {
491e07b27eSBarry Smith   if (scomm->color == 0) { return PETSC_TRUE; }
501e07b27eSBarry Smith   else { return PETSC_FALSE; }
511e07b27eSBarry Smith }
521e07b27eSBarry Smith 
531e07b27eSBarry Smith #undef __FUNCT__
541e07b27eSBarry Smith #define __FUNCT__ "private_PCTelescopeGetSubDM"
551e07b27eSBarry Smith DM private_PCTelescopeGetSubDM(PC_Telescope sred)
561e07b27eSBarry Smith {
57c6a0d831SBarry Smith   DM subdm = NULL;
581e07b27eSBarry Smith 
591e07b27eSBarry Smith   if (!isActiveRank(sred->psubcomm)) { subdm = NULL; }
601e07b27eSBarry Smith   else {
611e07b27eSBarry Smith     switch (sred->sr_type) {
621e07b27eSBarry Smith     case TELESCOPE_DEFAULT: subdm = NULL;
631e07b27eSBarry Smith       break;
641e07b27eSBarry Smith     case TELESCOPE_DMDA:    subdm = ((PC_Telescope_DMDACtx*)sred->dm_ctx)->dmrepart;
651e07b27eSBarry Smith       break;
661e07b27eSBarry Smith     case TELESCOPE_DMPLEX:  subdm = NULL;
671e07b27eSBarry Smith       break;
681e07b27eSBarry Smith     }
691e07b27eSBarry Smith   }
701e07b27eSBarry Smith   return(subdm);
711e07b27eSBarry Smith }
721e07b27eSBarry Smith 
731e07b27eSBarry Smith #undef __FUNCT__
741e07b27eSBarry Smith #define __FUNCT__ "PCTelescopeSetUp_default"
751e07b27eSBarry Smith PetscErrorCode PCTelescopeSetUp_default(PC pc,PC_Telescope sred)
761e07b27eSBarry Smith {
771e07b27eSBarry Smith   PetscErrorCode ierr;
781e07b27eSBarry Smith   PetscInt       m,M,bs,st,ed;
791e07b27eSBarry Smith   Vec            x,xred,yred,xtmp;
801e07b27eSBarry Smith   Mat            B;
811e07b27eSBarry Smith   MPI_Comm       comm,subcomm;
821e07b27eSBarry Smith   VecScatter     scatter;
831e07b27eSBarry Smith   IS             isin;
841e07b27eSBarry Smith 
851e07b27eSBarry Smith   PetscFunctionBegin;
861e07b27eSBarry Smith   ierr = PetscInfo(pc,"PCTelescope: setup (default)\n");CHKERRQ(ierr);
871e07b27eSBarry Smith   comm = PetscSubcommParent(sred->psubcomm);
881e07b27eSBarry Smith   subcomm = PetscSubcommChild(sred->psubcomm);
891e07b27eSBarry Smith 
901e07b27eSBarry Smith   ierr = PCGetOperators(pc,NULL,&B);CHKERRQ(ierr);
911e07b27eSBarry Smith   ierr = MatGetSize(B,&M,NULL);CHKERRQ(ierr);
921e07b27eSBarry Smith   ierr = MatGetBlockSize(B,&bs);CHKERRQ(ierr);
931e07b27eSBarry Smith   ierr = MatCreateVecs(B,&x,NULL);CHKERRQ(ierr);
941e07b27eSBarry Smith 
951e07b27eSBarry Smith   xred = NULL;
963ac26c5eSBarry Smith   m    = 0;
971e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
981e07b27eSBarry Smith     ierr = VecCreate(subcomm,&xred);CHKERRQ(ierr);
991e07b27eSBarry Smith     ierr = VecSetSizes(xred,PETSC_DECIDE,M);CHKERRQ(ierr);
1001e07b27eSBarry Smith     ierr = VecSetBlockSize(xred,bs);CHKERRQ(ierr);
1011e07b27eSBarry Smith     ierr = VecSetFromOptions(xred);CHKERRQ(ierr);
102ca43db0aSBarry Smith     ierr = VecGetLocalSize(xred,&m);CHKERRQ(ierr);
1031e07b27eSBarry Smith   }
1041e07b27eSBarry Smith 
1051e07b27eSBarry Smith   yred = NULL;
1061e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
1071e07b27eSBarry Smith     ierr = VecDuplicate(xred,&yred);CHKERRQ(ierr);
1081e07b27eSBarry Smith   }
1091e07b27eSBarry Smith 
1101e07b27eSBarry Smith   ierr = VecCreate(comm,&xtmp);CHKERRQ(ierr);
1111e07b27eSBarry Smith   ierr = VecSetSizes(xtmp,m,PETSC_DECIDE);CHKERRQ(ierr);
1121e07b27eSBarry Smith   ierr = VecSetBlockSize(xtmp,bs);CHKERRQ(ierr);
1131e07b27eSBarry Smith   ierr = VecSetType(xtmp,((PetscObject)x)->type_name);CHKERRQ(ierr);
1141e07b27eSBarry Smith 
1151e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
1161e07b27eSBarry Smith     ierr = VecGetOwnershipRange(xred,&st,&ed);CHKERRQ(ierr);
1171e07b27eSBarry Smith     ierr = ISCreateStride(comm,(ed-st),st,1,&isin);CHKERRQ(ierr);
1181e07b27eSBarry Smith   } else {
1191e07b27eSBarry Smith     ierr = VecGetOwnershipRange(x,&st,&ed);CHKERRQ(ierr);
1203ac26c5eSBarry Smith     ierr = ISCreateStride(comm,0,st,1,&isin);CHKERRQ(ierr);
1211e07b27eSBarry Smith   }
1221e07b27eSBarry Smith   ierr = ISSetBlockSize(isin,bs);CHKERRQ(ierr);
1231e07b27eSBarry Smith 
1241e07b27eSBarry Smith   ierr = VecScatterCreate(x,isin,xtmp,NULL,&scatter);CHKERRQ(ierr);
1251e07b27eSBarry Smith 
1261e07b27eSBarry Smith   sred->isin    = isin;
1271e07b27eSBarry Smith   sred->scatter = scatter;
1281e07b27eSBarry Smith   sred->xred    = xred;
1291e07b27eSBarry Smith   sred->yred    = yred;
1301e07b27eSBarry Smith   sred->xtmp    = xtmp;
1311e07b27eSBarry Smith   ierr = VecDestroy(&x);CHKERRQ(ierr);
1321e07b27eSBarry Smith   PetscFunctionReturn(0);
1331e07b27eSBarry Smith }
1341e07b27eSBarry Smith 
1351e07b27eSBarry Smith #undef __FUNCT__
1361e07b27eSBarry Smith #define __FUNCT__ "PCTelescopeMatCreate_default"
1371e07b27eSBarry Smith PetscErrorCode PCTelescopeMatCreate_default(PC pc,PC_Telescope sred,MatReuse reuse,Mat *A)
1381e07b27eSBarry Smith {
1391e07b27eSBarry Smith   PetscErrorCode ierr;
1401e07b27eSBarry Smith   MPI_Comm       comm,subcomm;
1411e07b27eSBarry Smith   Mat            Bred,B;
1421e07b27eSBarry Smith   PetscInt       nr,nc;
1431e07b27eSBarry Smith   IS             isrow,iscol;
1441e07b27eSBarry Smith   Mat            Blocal,*_Blocal;
1451e07b27eSBarry Smith 
1461e07b27eSBarry Smith   PetscFunctionBegin;
1471e07b27eSBarry Smith   ierr = PetscInfo(pc,"PCTelescope: updating the redundant preconditioned operator (default)\n");CHKERRQ(ierr);
1481e07b27eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
1491e07b27eSBarry Smith   subcomm = PetscSubcommChild(sred->psubcomm);
1501e07b27eSBarry Smith   ierr = PCGetOperators(pc,NULL,&B);CHKERRQ(ierr);
1511e07b27eSBarry Smith   ierr = MatGetSize(B,&nr,&nc);CHKERRQ(ierr);
1521e07b27eSBarry Smith   isrow = sred->isin;
1531e07b27eSBarry Smith   ierr = ISCreateStride(comm,nc,0,1,&iscol);CHKERRQ(ierr);
1541e07b27eSBarry Smith   ierr = MatGetSubMatrices(B,1,&isrow,&iscol,MAT_INITIAL_MATRIX,&_Blocal);CHKERRQ(ierr);
1551e07b27eSBarry Smith   Blocal = *_Blocal;
1561e07b27eSBarry Smith   ierr = PetscFree(_Blocal);CHKERRQ(ierr);
1571e07b27eSBarry Smith   Bred = NULL;
1581e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
1591e07b27eSBarry Smith     PetscInt mm;
1601e07b27eSBarry Smith 
1611e07b27eSBarry Smith     if (reuse != MAT_INITIAL_MATRIX) { Bred = *A; }
1621e07b27eSBarry Smith 
1631e07b27eSBarry Smith     ierr = MatGetSize(Blocal,&mm,NULL);CHKERRQ(ierr);
1641e07b27eSBarry Smith     ierr = MatCreateMPIMatConcatenateSeqMat(subcomm,Blocal,mm,reuse,&Bred);CHKERRQ(ierr);
1651e07b27eSBarry Smith   }
1661e07b27eSBarry Smith   *A = Bred;
1671e07b27eSBarry Smith   ierr = ISDestroy(&iscol);CHKERRQ(ierr);
1681e07b27eSBarry Smith   ierr = MatDestroy(&Blocal);CHKERRQ(ierr);
1691e07b27eSBarry Smith   PetscFunctionReturn(0);
1701e07b27eSBarry Smith }
1711e07b27eSBarry Smith 
1721e07b27eSBarry Smith #undef __FUNCT__
173392968a1SPatrick Sanan #define __FUNCT__ "PCTelescopeSubNullSpaceCreate_Telescope"
174392968a1SPatrick Sanan static PetscErrorCode PCTelescopeSubNullSpaceCreate_Telescope(PC pc,PC_Telescope sred,MatNullSpace nullspace,MatNullSpace *sub_nullspace)
1751e07b27eSBarry Smith {
1761e07b27eSBarry Smith   PetscErrorCode   ierr;
1771e07b27eSBarry Smith   PetscBool        has_const;
1781e07b27eSBarry Smith   const Vec        *vecs;
179c41e779fSDave May   Vec              *sub_vecs = NULL;
180392968a1SPatrick Sanan   PetscInt         i,k,n = 0;
1811e07b27eSBarry Smith   MPI_Comm         subcomm;
1821e07b27eSBarry Smith 
1831e07b27eSBarry Smith   PetscFunctionBegin;
1841e07b27eSBarry Smith   subcomm = PetscSubcommChild(sred->psubcomm);
1851e07b27eSBarry Smith   ierr = MatNullSpaceGetVecs(nullspace,&has_const,&n,&vecs);CHKERRQ(ierr);
1861e07b27eSBarry Smith 
1871e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
188e3acf2f7SBarry Smith     if (n) {
189e3acf2f7SBarry Smith       ierr = VecDuplicateVecs(sred->xred,n,&sub_vecs);CHKERRQ(ierr);
1901e07b27eSBarry Smith     }
1911e07b27eSBarry Smith   }
1921e07b27eSBarry Smith 
1931e07b27eSBarry Smith   /* copy entries */
1941e07b27eSBarry Smith   for (k=0; k<n; k++) {
1951e07b27eSBarry Smith     const PetscScalar *x_array;
1961e07b27eSBarry Smith     PetscScalar       *LA_sub_vec;
19713c30530SDave May     PetscInt          st,ed;
1981e07b27eSBarry Smith 
1991e07b27eSBarry Smith     /* pull in vector x->xtmp */
2001e07b27eSBarry Smith     ierr = VecScatterBegin(sred->scatter,vecs[k],sred->xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2011e07b27eSBarry Smith     ierr = VecScatterEnd(sred->scatter,vecs[k],sred->xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
20247856c66SBarry Smith     if (sub_vecs) {
203a04a6428SPatrick Sanan       /* copy vector entries into xred */
2041e07b27eSBarry Smith       ierr = VecGetArrayRead(sred->xtmp,&x_array);CHKERRQ(ierr);
205ea2b237eSDave May       if (sub_vecs[k]) {
2061e07b27eSBarry Smith         ierr = VecGetOwnershipRange(sub_vecs[k],&st,&ed);CHKERRQ(ierr);
2071e07b27eSBarry Smith         ierr = VecGetArray(sub_vecs[k],&LA_sub_vec);CHKERRQ(ierr);
2081e07b27eSBarry Smith         for (i=0; i<ed-st; i++) {
2091e07b27eSBarry Smith           LA_sub_vec[i] = x_array[i];
2101e07b27eSBarry Smith         }
2111e07b27eSBarry Smith         ierr = VecRestoreArray(sub_vecs[k],&LA_sub_vec);CHKERRQ(ierr);
2121e07b27eSBarry Smith       }
2131e07b27eSBarry Smith       ierr = VecRestoreArrayRead(sred->xtmp,&x_array);CHKERRQ(ierr);
2141e07b27eSBarry Smith     }
21547856c66SBarry Smith   }
2161e07b27eSBarry Smith 
2171e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
218d8b9d5b7SPatrick Sanan     /* create new (near) nullspace for redundant object */
219392968a1SPatrick Sanan     ierr = MatNullSpaceCreate(subcomm,has_const,n,sub_vecs,sub_nullspace);CHKERRQ(ierr);
220392968a1SPatrick Sanan     ierr = VecDestroyVecs(n,&sub_vecs);CHKERRQ(ierr);
221d8b9d5b7SPatrick Sanan     if (nullspace->remove) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Propagation of custom remove callbacks not supported when propagating (near) nullspaces with PCTelescope");
222d8b9d5b7SPatrick 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");
223d8b9d5b7SPatrick Sanan   }
224392968a1SPatrick Sanan   PetscFunctionReturn(0);
225392968a1SPatrick Sanan }
226392968a1SPatrick Sanan 
227392968a1SPatrick Sanan #undef __FUNCT__
228392968a1SPatrick Sanan #define __FUNCT__ "PCTelescopeMatNullSpaceCreate_default"
229392968a1SPatrick Sanan static PetscErrorCode PCTelescopeMatNullSpaceCreate_default(PC pc,PC_Telescope sred,Mat sub_mat)
230392968a1SPatrick Sanan {
231392968a1SPatrick Sanan   PetscErrorCode   ierr;
232392968a1SPatrick Sanan   Mat              B;
233392968a1SPatrick Sanan 
234392968a1SPatrick Sanan   PetscFunctionBegin;
235392968a1SPatrick Sanan   ierr = PCGetOperators(pc,NULL,&B);CHKERRQ(ierr);
236392968a1SPatrick Sanan 
237392968a1SPatrick Sanan   /* Propagate the nullspace if it exists */
238392968a1SPatrick Sanan   {
239392968a1SPatrick Sanan     MatNullSpace nullspace,sub_nullspace;
240392968a1SPatrick Sanan     ierr = MatGetNullSpace(B,&nullspace);CHKERRQ(ierr);
241392968a1SPatrick Sanan     if (nullspace) {
242392968a1SPatrick Sanan       ierr = PetscInfo(pc,"PCTelescope: generating nullspace (default)\n");CHKERRQ(ierr);
243392968a1SPatrick Sanan       ierr = PCTelescopeSubNullSpaceCreate_Telescope(pc,sred,nullspace,&sub_nullspace);CHKERRQ(ierr);
244392968a1SPatrick Sanan       if (isActiveRank(sred->psubcomm)) {
245392968a1SPatrick Sanan         ierr = MatSetNullSpace(sub_mat,sub_nullspace);CHKERRQ(ierr);
24641ff1ee9SPatrick Sanan         ierr = MatNullSpaceDestroy(&sub_nullspace);CHKERRQ(ierr);
2471e07b27eSBarry Smith       }
248392968a1SPatrick Sanan     }
249392968a1SPatrick Sanan   }
250392968a1SPatrick Sanan 
251392968a1SPatrick Sanan   /* Propagate the near nullspace if it exists */
252392968a1SPatrick Sanan   {
253392968a1SPatrick Sanan     MatNullSpace nearnullspace,sub_nearnullspace;
254392968a1SPatrick Sanan     ierr = MatGetNearNullSpace(B,&nearnullspace);CHKERRQ(ierr);
255392968a1SPatrick Sanan     if (nearnullspace) {
256392968a1SPatrick Sanan       ierr = PetscInfo(pc,"PCTelescope: generating near nullspace (default)\n");CHKERRQ(ierr);
257392968a1SPatrick Sanan       ierr = PCTelescopeSubNullSpaceCreate_Telescope(pc,sred,nearnullspace,&sub_nearnullspace);CHKERRQ(ierr);
258392968a1SPatrick Sanan       if (isActiveRank(sred->psubcomm)) {
259392968a1SPatrick Sanan         ierr = MatSetNearNullSpace(sub_mat,sub_nearnullspace);CHKERRQ(ierr);
260392968a1SPatrick Sanan         ierr = MatNullSpaceDestroy(&sub_nearnullspace);CHKERRQ(ierr);
261392968a1SPatrick Sanan       }
262392968a1SPatrick Sanan     }
263392968a1SPatrick Sanan   }
2641e07b27eSBarry Smith   PetscFunctionReturn(0);
2651e07b27eSBarry Smith }
2661e07b27eSBarry Smith 
2671e07b27eSBarry Smith #undef __FUNCT__
2681e07b27eSBarry Smith #define __FUNCT__ "PCView_Telescope"
2691e07b27eSBarry Smith static PetscErrorCode PCView_Telescope(PC pc,PetscViewer viewer)
2701e07b27eSBarry Smith {
2711e07b27eSBarry Smith   PC_Telescope     sred = (PC_Telescope)pc->data;
2721e07b27eSBarry Smith   PetscErrorCode   ierr;
2731e07b27eSBarry Smith   PetscBool        iascii,isstring;
2741e07b27eSBarry Smith   PetscViewer      subviewer;
2751e07b27eSBarry Smith 
2761e07b27eSBarry Smith   PetscFunctionBegin;
2771e07b27eSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
2781e07b27eSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr);
2791e07b27eSBarry Smith   if (iascii) {
2801e07b27eSBarry Smith     if (!sred->psubcomm) {
2811e07b27eSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Telescope: preconditioner not yet setup\n");CHKERRQ(ierr);
2821e07b27eSBarry Smith     } else {
2831e07b27eSBarry Smith       MPI_Comm    comm,subcomm;
2841e07b27eSBarry Smith       PetscMPIInt comm_size,subcomm_size;
2851e07b27eSBarry Smith       DM          dm,subdm;
2861e07b27eSBarry Smith 
2871e07b27eSBarry Smith       ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
2881e07b27eSBarry Smith       subdm = private_PCTelescopeGetSubDM(sred);
2891e07b27eSBarry Smith       comm = PetscSubcommParent(sred->psubcomm);
2901e07b27eSBarry Smith       subcomm = PetscSubcommChild(sred->psubcomm);
2911e07b27eSBarry Smith       ierr = MPI_Comm_size(comm,&comm_size);CHKERRQ(ierr);
2921e07b27eSBarry Smith       ierr = MPI_Comm_size(subcomm,&subcomm_size);CHKERRQ(ierr);
2931e07b27eSBarry Smith 
2941e07b27eSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Telescope: parent comm size reduction factor = %D\n",sred->redfactor);CHKERRQ(ierr);
2951e07b27eSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Telescope: comm_size = %d , subcomm_size = %d\n",(int)comm_size,(int)subcomm_size);CHKERRQ(ierr);
29648a10b22SPatrick Sanan       switch (sred->subcommtype) {
29748a10b22SPatrick Sanan         case PETSC_SUBCOMM_INTERLACED :
29848a10b22SPatrick Sanan           ierr = PetscViewerASCIIPrintf(viewer,"  Telescope: subcomm type: interlaced\n",sred->subcommtype);CHKERRQ(ierr);
29948a10b22SPatrick Sanan           break;
30048a10b22SPatrick Sanan         case PETSC_SUBCOMM_CONTIGUOUS :
30148a10b22SPatrick Sanan           ierr = PetscViewerASCIIPrintf(viewer,"  Telescope: subcomm type: contiguous\n",sred->subcommtype);CHKERRQ(ierr);
30248a10b22SPatrick Sanan           break;
30348a10b22SPatrick Sanan         default :
30448a10b22SPatrick Sanan           SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"General subcomm type not supported by PCTelescope");
30548a10b22SPatrick Sanan       }
3061e07b27eSBarry Smith       ierr = PetscViewerGetSubViewer(viewer,subcomm,&subviewer);CHKERRQ(ierr);
3071e07b27eSBarry Smith       if (isActiveRank(sred->psubcomm)) {
3081e07b27eSBarry Smith         ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr);
3091e07b27eSBarry Smith 
3101e07b27eSBarry Smith         if (dm && sred->ignore_dm) {
3111e07b27eSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: ignoring DM\n");CHKERRQ(ierr);
3121e07b27eSBarry Smith         }
3137c5279cbSDave May         if (sred->ignore_kspcomputeoperators) {
3147c5279cbSDave May           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: ignoring KSPComputeOperators\n");CHKERRQ(ierr);
3157c5279cbSDave May         }
3161e07b27eSBarry Smith         switch (sred->sr_type) {
3171e07b27eSBarry Smith         case TELESCOPE_DEFAULT:
3181e07b27eSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: using default setup\n");CHKERRQ(ierr);
3191e07b27eSBarry Smith           break;
3201e07b27eSBarry Smith         case TELESCOPE_DMDA:
3211e07b27eSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: DMDA detected\n");CHKERRQ(ierr);
3221e07b27eSBarry Smith           ierr = DMView_DMDAShort(subdm,subviewer);CHKERRQ(ierr);
3231e07b27eSBarry Smith           break;
3241e07b27eSBarry Smith         case TELESCOPE_DMPLEX:
3251e07b27eSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: DMPLEX detected\n");CHKERRQ(ierr);
3261e07b27eSBarry Smith           break;
3271e07b27eSBarry Smith         }
3281e07b27eSBarry Smith 
3291e07b27eSBarry Smith         ierr = KSPView(sred->ksp,subviewer);CHKERRQ(ierr);
3301e07b27eSBarry Smith         ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr);
3311e07b27eSBarry Smith       }
3321e07b27eSBarry Smith       ierr = PetscViewerRestoreSubViewer(viewer,subcomm,&subviewer);CHKERRQ(ierr);
3331e07b27eSBarry Smith     }
3341e07b27eSBarry Smith   }
3351e07b27eSBarry Smith   PetscFunctionReturn(0);
3361e07b27eSBarry Smith }
3371e07b27eSBarry Smith 
3381e07b27eSBarry Smith #undef __FUNCT__
3391e07b27eSBarry Smith #define __FUNCT__ "PCSetUp_Telescope"
3401e07b27eSBarry Smith static PetscErrorCode PCSetUp_Telescope(PC pc)
3411e07b27eSBarry Smith {
3421e07b27eSBarry Smith   PC_Telescope      sred = (PC_Telescope)pc->data;
3431e07b27eSBarry Smith   PetscErrorCode    ierr;
344bd49479cSSatish Balay   MPI_Comm          comm,subcomm=0;
3451e07b27eSBarry Smith   PCTelescopeType   sr_type;
3461e07b27eSBarry Smith 
3471e07b27eSBarry Smith   PetscFunctionBegin;
3481e07b27eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
3491e07b27eSBarry Smith 
3501e07b27eSBarry Smith   /* subcomm definition */
3511e07b27eSBarry Smith   if (!pc->setupcalled) {
3521e07b27eSBarry Smith     if (!sred->psubcomm) {
3531e07b27eSBarry Smith       ierr = PetscSubcommCreate(comm,&sred->psubcomm);CHKERRQ(ierr);
3541e07b27eSBarry Smith       ierr = PetscSubcommSetNumber(sred->psubcomm,sred->redfactor);CHKERRQ(ierr);
35548a10b22SPatrick Sanan       ierr = PetscSubcommSetType(sred->psubcomm,sred->subcommtype);CHKERRQ(ierr);
3561e07b27eSBarry Smith       ierr = PetscLogObjectMemory((PetscObject)pc,sizeof(PetscSubcomm));CHKERRQ(ierr);
3571e07b27eSBarry Smith     }
3581e07b27eSBarry Smith   }
3590f6f40a7SSatish Balay   subcomm = PetscSubcommChild(sred->psubcomm);
3601e07b27eSBarry Smith 
3611e07b27eSBarry Smith   /* internal KSP */
3621e07b27eSBarry Smith   if (!pc->setupcalled) {
3631e07b27eSBarry Smith     const char *prefix;
3641e07b27eSBarry Smith 
3651e07b27eSBarry Smith     if (isActiveRank(sred->psubcomm)) {
3661e07b27eSBarry Smith       ierr = KSPCreate(subcomm,&sred->ksp);CHKERRQ(ierr);
3671e07b27eSBarry Smith       ierr = KSPSetErrorIfNotConverged(sred->ksp,pc->erroriffailure);CHKERRQ(ierr);
3681e07b27eSBarry Smith       ierr = PetscObjectIncrementTabLevel((PetscObject)sred->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
3691e07b27eSBarry Smith       ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)sred->ksp);CHKERRQ(ierr);
3701e07b27eSBarry Smith       ierr = KSPSetType(sred->ksp,KSPPREONLY);CHKERRQ(ierr);
3711e07b27eSBarry Smith       ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
3721e07b27eSBarry Smith       ierr = KSPSetOptionsPrefix(sred->ksp,prefix);CHKERRQ(ierr);
3731e07b27eSBarry Smith       ierr = KSPAppendOptionsPrefix(sred->ksp,"telescope_");CHKERRQ(ierr);
3741e07b27eSBarry Smith     }
3751e07b27eSBarry Smith   }
3761e07b27eSBarry Smith   /* Determine type of setup/update */
3771e07b27eSBarry Smith   if (!pc->setupcalled) {
3781e07b27eSBarry Smith     PetscBool has_dm,same;
3791e07b27eSBarry Smith     DM        dm;
3801e07b27eSBarry Smith 
3811e07b27eSBarry Smith     sr_type = TELESCOPE_DEFAULT;
3821e07b27eSBarry Smith     has_dm = PETSC_FALSE;
3831e07b27eSBarry Smith     ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
3841e07b27eSBarry Smith     if (dm) { has_dm = PETSC_TRUE; }
3851e07b27eSBarry Smith     if (has_dm) {
3861e07b27eSBarry Smith       /* check for dmda */
3871e07b27eSBarry Smith       ierr = PetscObjectTypeCompare((PetscObject)dm,DMDA,&same);CHKERRQ(ierr);
3881e07b27eSBarry Smith       if (same) {
3891e07b27eSBarry Smith         ierr = PetscInfo(pc,"PCTelescope: found DMDA\n");CHKERRQ(ierr);
3901e07b27eSBarry Smith         sr_type = TELESCOPE_DMDA;
3911e07b27eSBarry Smith       }
3921e07b27eSBarry Smith       /* check for dmplex */
3931e07b27eSBarry Smith       ierr = PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&same);CHKERRQ(ierr);
3941e07b27eSBarry Smith       if (same) {
3951e07b27eSBarry Smith         PetscInfo(pc,"PCTelescope: found DMPLEX\n");
3961e07b27eSBarry Smith         sr_type = TELESCOPE_DMPLEX;
3971e07b27eSBarry Smith       }
3981e07b27eSBarry Smith     }
3991e07b27eSBarry Smith 
4001e07b27eSBarry Smith     if (sred->ignore_dm) {
4011e07b27eSBarry Smith       PetscInfo(pc,"PCTelescope: ignore DM\n");
4021e07b27eSBarry Smith       sr_type = TELESCOPE_DEFAULT;
4031e07b27eSBarry Smith     }
4041e07b27eSBarry Smith     sred->sr_type = sr_type;
4051e07b27eSBarry Smith   } else {
4061e07b27eSBarry Smith     sr_type = sred->sr_type;
4071e07b27eSBarry Smith   }
4081e07b27eSBarry Smith 
409d8b9d5b7SPatrick Sanan   /* set function pointers for repartition setup, matrix creation/update, matrix (near) nullspace, and reset functionality */
4101e07b27eSBarry Smith   switch (sr_type) {
4111e07b27eSBarry Smith   case TELESCOPE_DEFAULT:
4121e07b27eSBarry Smith     sred->pctelescope_setup_type              = PCTelescopeSetUp_default;
4131e07b27eSBarry Smith     sred->pctelescope_matcreate_type          = PCTelescopeMatCreate_default;
4141e07b27eSBarry Smith     sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_default;
4151e07b27eSBarry Smith     sred->pctelescope_reset_type              = NULL;
4161e07b27eSBarry Smith     break;
4171e07b27eSBarry Smith   case TELESCOPE_DMDA:
4181e07b27eSBarry Smith     pc->ops->apply                            = PCApply_Telescope_dmda;
419f650675bSDave May     pc->ops->applyrichardson                  = PCApplyRichardson_Telescope_dmda;
4201e07b27eSBarry Smith     sred->pctelescope_setup_type              = PCTelescopeSetUp_dmda;
4211e07b27eSBarry Smith     sred->pctelescope_matcreate_type          = PCTelescopeMatCreate_dmda;
4221e07b27eSBarry Smith     sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_dmda;
4231e07b27eSBarry Smith     sred->pctelescope_reset_type              = PCReset_Telescope_dmda;
4241e07b27eSBarry Smith     break;
425d8b9d5b7SPatrick Sanan   case TELESCOPE_DMPLEX: SETERRQ(comm,PETSC_ERR_SUP,"Support for DMPLEX is currently not available");
4261e07b27eSBarry Smith     break;
427a04a6428SPatrick Sanan   default: SETERRQ(comm,PETSC_ERR_SUP,"Only support for repartitioning DMDA is provided");
4281e07b27eSBarry Smith     break;
4291e07b27eSBarry Smith   }
4301e07b27eSBarry Smith 
4311e07b27eSBarry Smith   /* setup */
4321e07b27eSBarry Smith   if (sred->pctelescope_setup_type) {
4331e07b27eSBarry Smith     ierr = sred->pctelescope_setup_type(pc,sred);CHKERRQ(ierr);
4341e07b27eSBarry Smith   }
4351e07b27eSBarry Smith   /* update */
4361e07b27eSBarry Smith   if (!pc->setupcalled) {
4371e07b27eSBarry Smith     if (sred->pctelescope_matcreate_type) {
4381e07b27eSBarry Smith       ierr = sred->pctelescope_matcreate_type(pc,sred,MAT_INITIAL_MATRIX,&sred->Bred);CHKERRQ(ierr);
4391e07b27eSBarry Smith     }
4401e07b27eSBarry Smith     if (sred->pctelescope_matnullspacecreate_type) {
441392968a1SPatrick Sanan       ierr = sred->pctelescope_matnullspacecreate_type(pc,sred,sred->Bred);CHKERRQ(ierr);
4421e07b27eSBarry Smith     }
4431e07b27eSBarry Smith   } else {
4441e07b27eSBarry Smith     if (sred->pctelescope_matcreate_type) {
4451e07b27eSBarry Smith       ierr = sred->pctelescope_matcreate_type(pc,sred,MAT_REUSE_MATRIX,&sred->Bred);CHKERRQ(ierr);
4461e07b27eSBarry Smith     }
4471e07b27eSBarry Smith   }
4481e07b27eSBarry Smith 
4491e07b27eSBarry Smith   /* common - no construction */
4501e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
4511e07b27eSBarry Smith     ierr = KSPSetOperators(sred->ksp,sred->Bred,sred->Bred);CHKERRQ(ierr);
4521e07b27eSBarry Smith     if (pc->setfromoptionscalled && !pc->setupcalled){
4531e07b27eSBarry Smith       ierr = KSPSetFromOptions(sred->ksp);CHKERRQ(ierr);
4541e07b27eSBarry Smith     }
4551e07b27eSBarry Smith   }
4561e07b27eSBarry Smith   PetscFunctionReturn(0);
4571e07b27eSBarry Smith }
4581e07b27eSBarry Smith 
4591e07b27eSBarry Smith #undef __FUNCT__
4601e07b27eSBarry Smith #define __FUNCT__ "PCApply_Telescope"
4611e07b27eSBarry Smith static PetscErrorCode PCApply_Telescope(PC pc,Vec x,Vec y)
4621e07b27eSBarry Smith {
4631e07b27eSBarry Smith   PC_Telescope      sred = (PC_Telescope)pc->data;
4641e07b27eSBarry Smith   PetscErrorCode    ierr;
4651e07b27eSBarry Smith   Vec               xtmp,xred,yred;
46613c30530SDave May   PetscInt          i,st,ed;
4671e07b27eSBarry Smith   VecScatter        scatter;
4681e07b27eSBarry Smith   PetscScalar       *array;
4691e07b27eSBarry Smith   const PetscScalar *x_array;
4701e07b27eSBarry Smith 
4711e07b27eSBarry Smith   PetscFunctionBegin;
472*bf00f589SPatrick Sanan   ierr = PetscCitationsRegister(citation,&cited);CHKERRQ(ierr);
473*bf00f589SPatrick Sanan 
4741e07b27eSBarry Smith   xtmp    = sred->xtmp;
4751e07b27eSBarry Smith   scatter = sred->scatter;
4761e07b27eSBarry Smith   xred    = sred->xred;
4771e07b27eSBarry Smith   yred    = sred->yred;
4781e07b27eSBarry Smith 
4791e07b27eSBarry Smith   /* pull in vector x->xtmp */
4801e07b27eSBarry Smith   ierr = VecScatterBegin(scatter,x,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4811e07b27eSBarry Smith   ierr = VecScatterEnd(scatter,x,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4821e07b27eSBarry Smith 
483*bf00f589SPatrick Sanan   /* copy vector entries into xred */
4841e07b27eSBarry Smith   ierr = VecGetArrayRead(xtmp,&x_array);CHKERRQ(ierr);
4851e07b27eSBarry Smith   if (xred) {
4861e07b27eSBarry Smith     PetscScalar *LA_xred;
4871e07b27eSBarry Smith     ierr = VecGetOwnershipRange(xred,&st,&ed);CHKERRQ(ierr);
4881e07b27eSBarry Smith     ierr = VecGetArray(xred,&LA_xred);CHKERRQ(ierr);
4891e07b27eSBarry Smith     for (i=0; i<ed-st; i++) {
4901e07b27eSBarry Smith       LA_xred[i] = x_array[i];
4911e07b27eSBarry Smith     }
4921e07b27eSBarry Smith     ierr = VecRestoreArray(xred,&LA_xred);CHKERRQ(ierr);
4931e07b27eSBarry Smith   }
4941e07b27eSBarry Smith   ierr = VecRestoreArrayRead(xtmp,&x_array);CHKERRQ(ierr);
4951e07b27eSBarry Smith   /* solve */
4961e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
4971e07b27eSBarry Smith     ierr = KSPSolve(sred->ksp,xred,yred);CHKERRQ(ierr);
4981e07b27eSBarry Smith   }
4991e07b27eSBarry Smith   /* return vector */
5001e07b27eSBarry Smith   ierr = VecGetArray(xtmp,&array);CHKERRQ(ierr);
5011e07b27eSBarry Smith   if (yred) {
5021e07b27eSBarry Smith     const PetscScalar *LA_yred;
5031e07b27eSBarry Smith     ierr = VecGetOwnershipRange(yred,&st,&ed);CHKERRQ(ierr);
5041e07b27eSBarry Smith     ierr = VecGetArrayRead(yred,&LA_yred);CHKERRQ(ierr);
5051e07b27eSBarry Smith     for (i=0; i<ed-st; i++) {
5061e07b27eSBarry Smith       array[i] = LA_yred[i];
5071e07b27eSBarry Smith     }
5081e07b27eSBarry Smith     ierr = VecRestoreArrayRead(yred,&LA_yred);CHKERRQ(ierr);
5091e07b27eSBarry Smith   }
5101e07b27eSBarry Smith   ierr = VecRestoreArray(xtmp,&array);CHKERRQ(ierr);
5111e07b27eSBarry Smith   ierr = VecScatterBegin(scatter,xtmp,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5121e07b27eSBarry Smith   ierr = VecScatterEnd(scatter,xtmp,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5131e07b27eSBarry Smith   PetscFunctionReturn(0);
5141e07b27eSBarry Smith }
5151e07b27eSBarry Smith 
5161e07b27eSBarry Smith #undef __FUNCT__
517f650675bSDave May #define __FUNCT__ "PCApplyRichardson_Telescope"
518f650675bSDave 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)
519f650675bSDave May {
520f650675bSDave May   PC_Telescope      sred = (PC_Telescope)pc->data;
521f650675bSDave May   PetscErrorCode    ierr;
522a1d91a28SDave May   Vec               xtmp,yred;
523f650675bSDave May   PetscInt          i,st,ed;
524f650675bSDave May   VecScatter        scatter;
525f650675bSDave May   const PetscScalar *x_array;
526f650675bSDave May   PetscBool         default_init_guess_value;
527f650675bSDave May 
528f650675bSDave May   PetscFunctionBegin;
529f650675bSDave May   xtmp    = sred->xtmp;
530f650675bSDave May   scatter = sred->scatter;
531f650675bSDave May   yred    = sred->yred;
532f650675bSDave May 
533f650675bSDave May   if (its > 1) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCApplyRichardson_Telescope only supports max_it = 1");
534f650675bSDave May   *reason = (PCRichardsonConvergedReason)0;
535f650675bSDave May 
536f650675bSDave May   if (!zeroguess) {
537f650675bSDave May     ierr = PetscInfo(pc,"PCTelescope: Scattering y for non-zero initial guess\n");CHKERRQ(ierr);
538f650675bSDave May     /* pull in vector y->xtmp */
539f650675bSDave May     ierr = VecScatterBegin(scatter,y,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
540f650675bSDave May     ierr = VecScatterEnd(scatter,y,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
541f650675bSDave May 
542*bf00f589SPatrick Sanan     /* copy vector entries into xred */
543f650675bSDave May     ierr = VecGetArrayRead(xtmp,&x_array);CHKERRQ(ierr);
544f650675bSDave May     if (yred) {
545f650675bSDave May       PetscScalar *LA_yred;
546f650675bSDave May       ierr = VecGetOwnershipRange(yred,&st,&ed);CHKERRQ(ierr);
547f650675bSDave May       ierr = VecGetArray(yred,&LA_yred);CHKERRQ(ierr);
548f650675bSDave May       for (i=0; i<ed-st; i++) {
549f650675bSDave May         LA_yred[i] = x_array[i];
550f650675bSDave May       }
551f650675bSDave May       ierr = VecRestoreArray(yred,&LA_yred);CHKERRQ(ierr);
552f650675bSDave May     }
553f650675bSDave May     ierr = VecRestoreArrayRead(xtmp,&x_array);CHKERRQ(ierr);
554f650675bSDave May   }
555f650675bSDave May 
556f650675bSDave May   if (isActiveRank(sred->psubcomm)) {
557f650675bSDave May     ierr = KSPGetInitialGuessNonzero(sred->ksp,&default_init_guess_value);CHKERRQ(ierr);
558f650675bSDave May     if (!zeroguess) ierr = KSPSetInitialGuessNonzero(sred->ksp,PETSC_TRUE);CHKERRQ(ierr);
559f650675bSDave May   }
560f650675bSDave May 
561f650675bSDave May   ierr = PCApply_Telescope(pc,x,y);CHKERRQ(ierr);
562f650675bSDave May 
563f650675bSDave May   if (isActiveRank(sred->psubcomm)) {
564f650675bSDave May     ierr = KSPSetInitialGuessNonzero(sred->ksp,default_init_guess_value);CHKERRQ(ierr);
565f650675bSDave May   }
566f650675bSDave May 
567f650675bSDave May   if (!*reason) *reason = PCRICHARDSON_CONVERGED_ITS;
568f650675bSDave May   *outits = 1;
569f650675bSDave May   PetscFunctionReturn(0);
570f650675bSDave May }
571f650675bSDave May 
572f650675bSDave May #undef __FUNCT__
5731e07b27eSBarry Smith #define __FUNCT__ "PCReset_Telescope"
5741e07b27eSBarry Smith static PetscErrorCode PCReset_Telescope(PC pc)
5751e07b27eSBarry Smith {
5761e07b27eSBarry Smith   PC_Telescope   sred = (PC_Telescope)pc->data;
5771e07b27eSBarry Smith   PetscErrorCode ierr;
5781e07b27eSBarry Smith 
5791e07b27eSBarry Smith   ierr = ISDestroy(&sred->isin);CHKERRQ(ierr);
5801e07b27eSBarry Smith   ierr = VecScatterDestroy(&sred->scatter);CHKERRQ(ierr);
581e3acf2f7SBarry Smith   ierr = VecDestroy(&sred->xred);CHKERRQ(ierr);
582e3acf2f7SBarry Smith   ierr = VecDestroy(&sred->yred);CHKERRQ(ierr);
583e3acf2f7SBarry Smith   ierr = VecDestroy(&sred->xtmp);CHKERRQ(ierr);
584e3acf2f7SBarry Smith   ierr = MatDestroy(&sred->Bred);CHKERRQ(ierr);
585e3acf2f7SBarry Smith   ierr = KSPReset(sred->ksp);CHKERRQ(ierr);
5861e07b27eSBarry Smith   if (sred->pctelescope_reset_type) {
5871e07b27eSBarry Smith     ierr = sred->pctelescope_reset_type(pc);CHKERRQ(ierr);
5881e07b27eSBarry Smith   }
5891e07b27eSBarry Smith   PetscFunctionReturn(0);
5901e07b27eSBarry Smith }
5911e07b27eSBarry Smith 
5921e07b27eSBarry Smith #undef __FUNCT__
5931e07b27eSBarry Smith #define __FUNCT__ "PCDestroy_Telescope"
5941e07b27eSBarry Smith static PetscErrorCode PCDestroy_Telescope(PC pc)
5951e07b27eSBarry Smith {
5961e07b27eSBarry Smith   PC_Telescope     sred = (PC_Telescope)pc->data;
5971e07b27eSBarry Smith   PetscErrorCode   ierr;
5981e07b27eSBarry Smith 
5991e07b27eSBarry Smith   PetscFunctionBegin;
6001e07b27eSBarry Smith   ierr = PCReset_Telescope(pc);CHKERRQ(ierr);
601e3acf2f7SBarry Smith   ierr = KSPDestroy(&sred->ksp);CHKERRQ(ierr);
6021e07b27eSBarry Smith   ierr = PetscSubcommDestroy(&sred->psubcomm);CHKERRQ(ierr);
603e3acf2f7SBarry Smith   ierr = PetscFree(sred->dm_ctx);CHKERRQ(ierr);
604e3acf2f7SBarry Smith   ierr = PetscFree(pc->data);CHKERRQ(ierr);
6051e07b27eSBarry Smith   PetscFunctionReturn(0);
6061e07b27eSBarry Smith }
6071e07b27eSBarry Smith 
6081e07b27eSBarry Smith #undef __FUNCT__
6091e07b27eSBarry Smith #define __FUNCT__ "PCSetFromOptions_Telescope"
6104416b707SBarry Smith static PetscErrorCode PCSetFromOptions_Telescope(PetscOptionItems *PetscOptionsObject,PC pc)
6111e07b27eSBarry Smith {
6121e07b27eSBarry Smith   PC_Telescope     sred = (PC_Telescope)pc->data;
6131e07b27eSBarry Smith   PetscErrorCode   ierr;
6141e07b27eSBarry Smith   MPI_Comm         comm;
6151e07b27eSBarry Smith   PetscMPIInt      size;
61648a10b22SPatrick Sanan   PetscBool        flg;
61748a10b22SPatrick Sanan   PetscSubcommType subcommtype;
6181e07b27eSBarry Smith 
6191e07b27eSBarry Smith   PetscFunctionBegin;
6201e07b27eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
6211e07b27eSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
6221e07b27eSBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"Telescope options");CHKERRQ(ierr);
62348a10b22SPatrick Sanan   ierr = PetscOptionsEnum("-pc_telescope_subcomm_type","Subcomm type (interlaced or contiguous)","PCTelescopeSetSubcommType",PetscSubcommTypes,(PetscEnum)sred->subcommtype,(PetscEnum*)&subcommtype,&flg);CHKERRQ(ierr);
62448a10b22SPatrick Sanan   if (flg) {
62548a10b22SPatrick Sanan     ierr = PCTelescopeSetSubcommType(pc,subcommtype);CHKERRQ(ierr);
62648a10b22SPatrick Sanan   }
6271e07b27eSBarry Smith   ierr = PetscOptionsInt("-pc_telescope_reduction_factor","Factor to reduce comm size by","PCTelescopeSetReductionFactor",sred->redfactor,&sred->redfactor,0);CHKERRQ(ierr);
6281e07b27eSBarry Smith   if (sred->redfactor > size) SETERRQ(comm,PETSC_ERR_ARG_WRONG,"-pc_telescope_reduction_factor <= comm size");
6291e07b27eSBarry Smith   ierr = PetscOptionsBool("-pc_telescope_ignore_dm","Ignore any DM attached to the PC","PCTelescopeSetIgnoreDM",sred->ignore_dm,&sred->ignore_dm,0);CHKERRQ(ierr);
6307c5279cbSDave May   ierr = PetscOptionsBool("-pc_telescope_ignore_kspcomputeoperators","Ignore method used to compute A","PCTelescopeSetIgnoreKSPComputeOperators",sred->ignore_kspcomputeoperators,&sred->ignore_kspcomputeoperators,0);CHKERRQ(ierr);
6311e07b27eSBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
6321e07b27eSBarry Smith   PetscFunctionReturn(0);
6331e07b27eSBarry Smith }
6341e07b27eSBarry Smith 
6351e07b27eSBarry Smith /* PC simplementation specific API's */
6361e07b27eSBarry Smith 
63748a10b22SPatrick Sanan #undef __FUNCT__
63848a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeGetKSP_Telescope"
6391e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetKSP_Telescope(PC pc,KSP *ksp)
6401e07b27eSBarry Smith {
6411e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
642bd49479cSSatish Balay   PetscFunctionBegin;
6431e07b27eSBarry Smith   if (ksp) *ksp = red->ksp;
644bd49479cSSatish Balay   PetscFunctionReturn(0);
6451e07b27eSBarry Smith }
6461e07b27eSBarry Smith 
64748a10b22SPatrick Sanan #undef __FUNCT__
64848a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeGetSubcommType_Telescope"
64948a10b22SPatrick Sanan static PetscErrorCode PCTelescopeGetSubcommType_Telescope(PC pc,PetscSubcommType *subcommtype)
65048a10b22SPatrick Sanan {
65148a10b22SPatrick Sanan   PC_Telescope red = (PC_Telescope)pc->data;
65248a10b22SPatrick Sanan   PetscFunctionBegin;
65348a10b22SPatrick Sanan   if (subcommtype) *subcommtype = red->subcommtype;
65448a10b22SPatrick Sanan   PetscFunctionReturn(0);
65548a10b22SPatrick Sanan }
65648a10b22SPatrick Sanan 
65748a10b22SPatrick Sanan #undef __FUNCT__
65848a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeSetSubcommType_Telescope"
65948a10b22SPatrick Sanan static PetscErrorCode PCTelescopeSetSubcommType_Telescope(PC pc,PetscSubcommType subcommtype)
66048a10b22SPatrick Sanan {
66148a10b22SPatrick Sanan   PC_Telescope     red = (PC_Telescope)pc->data;
66248a10b22SPatrick Sanan 
66348a10b22SPatrick Sanan   PetscFunctionBegin;
66448a10b22SPatrick 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.");
66548a10b22SPatrick Sanan   red->subcommtype = subcommtype;
66648a10b22SPatrick Sanan   PetscFunctionReturn(0);
66748a10b22SPatrick Sanan }
66848a10b22SPatrick Sanan 
66948a10b22SPatrick Sanan #undef __FUNCT__
67048a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeGetReductionFactor_Telescope"
6711e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetReductionFactor_Telescope(PC pc,PetscInt *fact)
6721e07b27eSBarry Smith {
6731e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
674bd49479cSSatish Balay   PetscFunctionBegin;
6751e07b27eSBarry Smith   if (fact) *fact = red->redfactor;
676bd49479cSSatish Balay   PetscFunctionReturn(0);
6771e07b27eSBarry Smith }
6781e07b27eSBarry Smith 
67948a10b22SPatrick Sanan #undef __FUNCT__
68048a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeSetReductionFactor_Telescope"
6811e07b27eSBarry Smith static PetscErrorCode PCTelescopeSetReductionFactor_Telescope(PC pc,PetscInt fact)
6821e07b27eSBarry Smith {
6831e07b27eSBarry Smith   PC_Telescope     red = (PC_Telescope)pc->data;
6841e07b27eSBarry Smith   PetscMPIInt      size;
6851e07b27eSBarry Smith   PetscErrorCode   ierr;
6861e07b27eSBarry Smith 
687bd49479cSSatish Balay   PetscFunctionBegin;
6881e07b27eSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
6891e07b27eSBarry Smith   if (fact <= 0) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Reduction factor of telescoping PC %D must be positive",fact);
6901e07b27eSBarry Smith   if (fact > size) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Reduction factor of telescoping PC %D must be <= comm.size",fact);
6911e07b27eSBarry Smith   red->redfactor = fact;
692bd49479cSSatish Balay   PetscFunctionReturn(0);
6931e07b27eSBarry Smith }
6941e07b27eSBarry Smith 
69548a10b22SPatrick Sanan #undef __FUNCT__
69648a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeGetIgnoreDM_Telescope"
6971e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetIgnoreDM_Telescope(PC pc,PetscBool *v)
6981e07b27eSBarry Smith {
6991e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
700bd49479cSSatish Balay   PetscFunctionBegin;
7011e07b27eSBarry Smith   if (v) *v = red->ignore_dm;
702bd49479cSSatish Balay   PetscFunctionReturn(0);
7031e07b27eSBarry Smith }
70448a10b22SPatrick Sanan 
70548a10b22SPatrick Sanan #undef __FUNCT__
70648a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeSetIgnoreDM_Telescope"
7071e07b27eSBarry Smith static PetscErrorCode PCTelescopeSetIgnoreDM_Telescope(PC pc,PetscBool v)
7081e07b27eSBarry Smith {
7091e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
710bd49479cSSatish Balay   PetscFunctionBegin;
7111e07b27eSBarry Smith   red->ignore_dm = v;
712bd49479cSSatish Balay   PetscFunctionReturn(0);
7131e07b27eSBarry Smith }
7141e07b27eSBarry Smith 
71548a10b22SPatrick Sanan #undef __FUNCT__
71648a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeGetIgnoreKSPComputeOperators_Telescope"
7170ae7c45bSDave May static PetscErrorCode PCTelescopeGetIgnoreKSPComputeOperators_Telescope(PC pc,PetscBool *v)
7180ae7c45bSDave May {
7190ae7c45bSDave May   PC_Telescope red = (PC_Telescope)pc->data;
7200ae7c45bSDave May   PetscFunctionBegin;
7210ae7c45bSDave May   if (v) *v = red->ignore_kspcomputeoperators;
7220ae7c45bSDave May   PetscFunctionReturn(0);
7230ae7c45bSDave May }
72448a10b22SPatrick Sanan 
72548a10b22SPatrick Sanan #undef __FUNCT__
72648a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeSetIgnoreKSPComputeOperators_Telescope"
7270ae7c45bSDave May static PetscErrorCode PCTelescopeSetIgnoreKSPComputeOperators_Telescope(PC pc,PetscBool v)
7280ae7c45bSDave May {
7290ae7c45bSDave May   PC_Telescope red = (PC_Telescope)pc->data;
7300ae7c45bSDave May   PetscFunctionBegin;
7310ae7c45bSDave May   red->ignore_kspcomputeoperators = v;
7320ae7c45bSDave May   PetscFunctionReturn(0);
7330ae7c45bSDave May }
7340ae7c45bSDave May 
73548a10b22SPatrick Sanan #undef __FUNCT__
73648a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeGetDM_Telescope"
7371e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetDM_Telescope(PC pc,DM *dm)
7381e07b27eSBarry Smith {
7391e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
740bd49479cSSatish Balay   PetscFunctionBegin;
7411e07b27eSBarry Smith   *dm = private_PCTelescopeGetSubDM(red);
742bd49479cSSatish Balay   PetscFunctionReturn(0);
7431e07b27eSBarry Smith }
7441e07b27eSBarry Smith 
7450f43ea10SBarry Smith #undef __FUNCT__
7460f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeGetKSP"
7471e07b27eSBarry Smith /*@
7481e07b27eSBarry Smith  PCTelescopeGetKSP - Gets the KSP created by the telescoping PC.
7491e07b27eSBarry Smith 
7501e07b27eSBarry Smith  Not Collective
7511e07b27eSBarry Smith 
7521e07b27eSBarry Smith  Input Parameter:
7531e07b27eSBarry Smith .  pc - the preconditioner context
7541e07b27eSBarry Smith 
7551e07b27eSBarry Smith  Output Parameter:
7561e07b27eSBarry Smith .  subksp - the KSP defined the smaller set of processes
7571e07b27eSBarry Smith 
7581e07b27eSBarry Smith  Level: advanced
7591e07b27eSBarry Smith 
7601e07b27eSBarry Smith .keywords: PC, telescopting solve
7611e07b27eSBarry Smith @*/
7621e07b27eSBarry Smith PetscErrorCode PCTelescopeGetKSP(PC pc,KSP *subksp)
7631e07b27eSBarry Smith {
764bd49479cSSatish Balay   PetscErrorCode ierr;
765bd49479cSSatish Balay   PetscFunctionBegin;
766163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetKSP_C",(PC,KSP*),(pc,subksp));CHKERRQ(ierr);
767bd49479cSSatish Balay   PetscFunctionReturn(0);
7681e07b27eSBarry Smith }
7691e07b27eSBarry Smith 
7700f43ea10SBarry Smith #undef __FUNCT__
7710f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeGetReductionFactor"
7721e07b27eSBarry Smith /*@
7731e07b27eSBarry Smith  PCTelescopeGetReductionFactor - Gets the factor by which the original number of processes has been reduced by.
7741e07b27eSBarry Smith 
7751e07b27eSBarry Smith  Not Collective
7761e07b27eSBarry Smith 
7771e07b27eSBarry Smith  Input Parameter:
7781e07b27eSBarry Smith .  pc - the preconditioner context
7791e07b27eSBarry Smith 
7801e07b27eSBarry Smith  Output Parameter:
7811e07b27eSBarry Smith .  fact - the reduction factor
7821e07b27eSBarry Smith 
7831e07b27eSBarry Smith  Level: advanced
7841e07b27eSBarry Smith 
7851e07b27eSBarry Smith .keywords: PC, telescoping solve
7861e07b27eSBarry Smith @*/
7871e07b27eSBarry Smith PetscErrorCode PCTelescopeGetReductionFactor(PC pc,PetscInt *fact)
7881e07b27eSBarry Smith {
789bd49479cSSatish Balay   PetscErrorCode ierr;
790bd49479cSSatish Balay   PetscFunctionBegin;
791163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetReductionFactor_C",(PC,PetscInt*),(pc,fact));CHKERRQ(ierr);
792bd49479cSSatish Balay   PetscFunctionReturn(0);
7931e07b27eSBarry Smith }
7941e07b27eSBarry Smith 
7950f43ea10SBarry Smith #undef __FUNCT__
7960f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeSetReductionFactor"
7971e07b27eSBarry Smith /*@
7981e07b27eSBarry Smith  PCTelescopeSetReductionFactor - Sets the factor by which the original number of processes has been reduced by.
7991e07b27eSBarry Smith 
8001e07b27eSBarry Smith  Not Collective
8011e07b27eSBarry Smith 
8021e07b27eSBarry Smith  Input Parameter:
8031e07b27eSBarry Smith .  pc - the preconditioner context
8041e07b27eSBarry Smith 
8051e07b27eSBarry Smith  Output Parameter:
8061e07b27eSBarry Smith .  fact - the reduction factor
8071e07b27eSBarry Smith 
8081e07b27eSBarry Smith  Level: advanced
8091e07b27eSBarry Smith 
8101e07b27eSBarry Smith .keywords: PC, telescoping solve
8111e07b27eSBarry Smith @*/
8121e07b27eSBarry Smith PetscErrorCode PCTelescopeSetReductionFactor(PC pc,PetscInt fact)
8131e07b27eSBarry Smith {
814bd49479cSSatish Balay   PetscErrorCode ierr;
815bd49479cSSatish Balay   PetscFunctionBegin;
816bd49479cSSatish Balay   ierr = PetscTryMethod(pc,"PCTelescopeSetReductionFactor_C",(PC,PetscInt),(pc,fact));CHKERRQ(ierr);
817bd49479cSSatish Balay   PetscFunctionReturn(0);
8181e07b27eSBarry Smith }
8191e07b27eSBarry Smith 
8200f43ea10SBarry Smith #undef __FUNCT__
8210f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeGetIgnoreDM"
8221e07b27eSBarry Smith /*@
8231e07b27eSBarry Smith  PCTelescopeGetIgnoreDM - Get the flag indicating if any DM attached to the PC will be used.
8241e07b27eSBarry Smith 
8251e07b27eSBarry Smith  Not Collective
8261e07b27eSBarry Smith 
8271e07b27eSBarry Smith  Input Parameter:
8281e07b27eSBarry Smith .  pc - the preconditioner context
8291e07b27eSBarry Smith 
8301e07b27eSBarry Smith  Output Parameter:
8311e07b27eSBarry Smith .  v - the flag
8321e07b27eSBarry Smith 
8331e07b27eSBarry Smith  Level: advanced
8341e07b27eSBarry Smith 
8351e07b27eSBarry Smith .keywords: PC, telescoping solve
8361e07b27eSBarry Smith @*/
8371e07b27eSBarry Smith PetscErrorCode PCTelescopeGetIgnoreDM(PC pc,PetscBool *v)
8381e07b27eSBarry Smith {
839bd49479cSSatish Balay   PetscErrorCode ierr;
840bd49479cSSatish Balay   PetscFunctionBegin;
841163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetIgnoreDM_C",(PC,PetscBool*),(pc,v));CHKERRQ(ierr);
842bd49479cSSatish Balay   PetscFunctionReturn(0);
8431e07b27eSBarry Smith }
8441e07b27eSBarry Smith 
8450f43ea10SBarry Smith #undef __FUNCT__
8460f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeSetIgnoreDM"
8471e07b27eSBarry Smith /*@
8481e07b27eSBarry Smith  PCTelescopeSetIgnoreDM - Set a flag to ignore any DM attached to the PC.
8491e07b27eSBarry Smith 
8501e07b27eSBarry Smith  Not Collective
8511e07b27eSBarry Smith 
8521e07b27eSBarry Smith  Input Parameter:
8531e07b27eSBarry Smith .  pc - the preconditioner context
8541e07b27eSBarry Smith 
8551e07b27eSBarry Smith  Output Parameter:
8561e07b27eSBarry Smith .  v - Use PETSC_TRUE to ignore any DM
8571e07b27eSBarry Smith 
8581e07b27eSBarry Smith  Level: advanced
8591e07b27eSBarry Smith 
8601e07b27eSBarry Smith .keywords: PC, telescoping solve
8611e07b27eSBarry Smith @*/
862bfd6bcc6SSatish Balay PetscErrorCode PCTelescopeSetIgnoreDM(PC pc,PetscBool v)
8631e07b27eSBarry Smith {
864bd49479cSSatish Balay   PetscErrorCode ierr;
865bd49479cSSatish Balay   PetscFunctionBegin;
866bd49479cSSatish Balay   ierr = PetscTryMethod(pc,"PCTelescopeSetIgnoreDM_C",(PC,PetscBool),(pc,v));CHKERRQ(ierr);
867bd49479cSSatish Balay   PetscFunctionReturn(0);
8681e07b27eSBarry Smith }
8691e07b27eSBarry Smith 
8700f43ea10SBarry Smith #undef __FUNCT__
8710f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeGetIgnoreKSPComputeOperators"
8721e07b27eSBarry Smith /*@
8730ae7c45bSDave May  PCTelescopeGetIgnoreKSPComputeOperators - Get the flag indicating if KSPComputeOperators will be used.
8740ae7c45bSDave May 
8750ae7c45bSDave May  Not Collective
8760ae7c45bSDave May 
8770ae7c45bSDave May  Input Parameter:
8780ae7c45bSDave May .  pc - the preconditioner context
8790ae7c45bSDave May 
8800ae7c45bSDave May  Output Parameter:
8810ae7c45bSDave May .  v - the flag
8820ae7c45bSDave May 
8830ae7c45bSDave May  Level: advanced
8840ae7c45bSDave May 
8850ae7c45bSDave May .keywords: PC, telescoping solve
8860ae7c45bSDave May @*/
8870ae7c45bSDave May PetscErrorCode PCTelescopeGetIgnoreKSPComputeOperators(PC pc,PetscBool *v)
8880ae7c45bSDave May {
8890ae7c45bSDave May   PetscErrorCode ierr;
8900ae7c45bSDave May   PetscFunctionBegin;
891163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetIgnoreKSPComputeOperators_C",(PC,PetscBool*),(pc,v));CHKERRQ(ierr);
8920ae7c45bSDave May   PetscFunctionReturn(0);
8930ae7c45bSDave May }
8940ae7c45bSDave May 
8950f43ea10SBarry Smith #undef __FUNCT__
8960f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeSetIgnoreKSPComputeOperators"
8970ae7c45bSDave May /*@
8980ae7c45bSDave May  PCTelescopeSetIgnoreKSPComputeOperators - Set a flag to ignore KSPComputeOperators.
8990ae7c45bSDave May 
9000ae7c45bSDave May  Not Collective
9010ae7c45bSDave May 
9020ae7c45bSDave May  Input Parameter:
9030ae7c45bSDave May .  pc - the preconditioner context
9040ae7c45bSDave May 
9050ae7c45bSDave May  Output Parameter:
906a954d8f4SDave May .  v - Use PETSC_TRUE to ignore the method (if defined) set via KSPSetComputeOperators on pc
9070ae7c45bSDave May 
9080ae7c45bSDave May  Level: advanced
9090ae7c45bSDave May 
9100ae7c45bSDave May .keywords: PC, telescoping solve
9110ae7c45bSDave May @*/
9120ae7c45bSDave May PetscErrorCode PCTelescopeSetIgnoreKSPComputeOperators(PC pc,PetscBool v)
9130ae7c45bSDave May {
9140ae7c45bSDave May   PetscErrorCode ierr;
9150ae7c45bSDave May   PetscFunctionBegin;
9160ae7c45bSDave May   ierr = PetscTryMethod(pc,"PCTelescopeSetIgnoreKSPComputeOperators_C",(PC,PetscBool),(pc,v));CHKERRQ(ierr);
9170ae7c45bSDave May   PetscFunctionReturn(0);
9180ae7c45bSDave May }
9190ae7c45bSDave May 
9200f43ea10SBarry Smith #undef __FUNCT__
9210f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeGetDM"
9220ae7c45bSDave May /*@
9231e07b27eSBarry Smith  PCTelescopeGetDM - Get the re-partitioned DM attached to the sub KSP.
9241e07b27eSBarry Smith 
9251e07b27eSBarry Smith  Not Collective
9261e07b27eSBarry Smith 
9271e07b27eSBarry Smith  Input Parameter:
9281e07b27eSBarry Smith .  pc - the preconditioner context
9291e07b27eSBarry Smith 
9301e07b27eSBarry Smith  Output Parameter:
9311e07b27eSBarry Smith .  subdm - The re-partitioned DM
9321e07b27eSBarry Smith 
9331e07b27eSBarry Smith  Level: advanced
9341e07b27eSBarry Smith 
9351e07b27eSBarry Smith .keywords: PC, telescoping solve
9361e07b27eSBarry Smith @*/
9371e07b27eSBarry Smith PetscErrorCode PCTelescopeGetDM(PC pc,DM *subdm)
9381e07b27eSBarry Smith {
939bd49479cSSatish Balay   PetscErrorCode ierr;
940bd49479cSSatish Balay   PetscFunctionBegin;
941163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetDM_C",(PC,DM*),(pc,subdm));CHKERRQ(ierr);
942bd49479cSSatish Balay   PetscFunctionReturn(0);
9431e07b27eSBarry Smith }
9441e07b27eSBarry Smith 
9450f43ea10SBarry Smith #undef __FUNCT__
9460f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeSetSubcommType"
94748a10b22SPatrick Sanan /*@
94848a10b22SPatrick Sanan  PCTelescopeSetSubcommType - set subcommunicator type (interlaced or contiguous)
94948a10b22SPatrick Sanan 
95048a10b22SPatrick Sanan  Logically Collective
95148a10b22SPatrick Sanan 
95248a10b22SPatrick Sanan  Input Parameter:
9531dae98e4SBarry Smith +  pc - the preconditioner context
9541dae98e4SBarry Smith -  subcommtype - the subcommunicator type (see PetscSubcommType)
95548a10b22SPatrick Sanan 
95648a10b22SPatrick Sanan  Level: advanced
95748a10b22SPatrick Sanan 
95848a10b22SPatrick Sanan .keywords: PC, telescoping solve
95948a10b22SPatrick Sanan 
96048a10b22SPatrick Sanan .seealso: PetscSubcommType, PetscSubcomm, PCTELESCOPE
96148a10b22SPatrick Sanan @*/
96248a10b22SPatrick Sanan PetscErrorCode PCTelescopeSetSubcommType(PC pc, PetscSubcommType subcommtype)
96348a10b22SPatrick Sanan {
96448a10b22SPatrick Sanan   PetscErrorCode ierr;
96548a10b22SPatrick Sanan   PetscFunctionBegin;
96648a10b22SPatrick Sanan   ierr = PetscTryMethod(pc,"PCTelescopeSetSubcommType_C",(PC,PetscSubcommType),(pc,subcommtype));CHKERRQ(ierr);
96748a10b22SPatrick Sanan   PetscFunctionReturn(0);
96848a10b22SPatrick Sanan }
96948a10b22SPatrick Sanan 
9700f43ea10SBarry Smith #undef __FUNCT__
9711dae98e4SBarry Smith #define __FUNCT__ "PCTelescopeGetSubcommType"
97248a10b22SPatrick Sanan /*@
97348a10b22SPatrick Sanan  PCTelescopeGetSubcommType - Get the subcommunicator type (interlaced or contiguous)
97448a10b22SPatrick Sanan 
97548a10b22SPatrick Sanan  Not Collective
97648a10b22SPatrick Sanan 
97748a10b22SPatrick Sanan  Input Parameter:
97848a10b22SPatrick Sanan .  pc - the preconditioner context
97948a10b22SPatrick Sanan 
98048a10b22SPatrick Sanan  Output Parameter:
98148a10b22SPatrick Sanan .  subcommtype - the subcommunicator type (see PetscSubcommType)
98248a10b22SPatrick Sanan 
98348a10b22SPatrick Sanan  Level: advanced
98448a10b22SPatrick Sanan 
98548a10b22SPatrick Sanan .keywords: PC, telescoping solve
98648a10b22SPatrick Sanan 
9871dae98e4SBarry Smith .seealso: PetscSubcomm, PetscSubcommType, PCTELESCOPE
98848a10b22SPatrick Sanan @*/
9891dae98e4SBarry Smith PetscErrorCode PCTelescopeGetSubcommType(PC pc, PetscSubcommType *subcommtype)
99048a10b22SPatrick Sanan {
99148a10b22SPatrick Sanan   PetscErrorCode ierr;
99248a10b22SPatrick Sanan   PetscFunctionBegin;
99348a10b22SPatrick Sanan   ierr = PetscUseMethod(pc,"PCTelescopeGetSubcommType_C",(PC,PetscSubcommType*),(pc,subcommtype));CHKERRQ(ierr);
99448a10b22SPatrick Sanan   PetscFunctionReturn(0);
99548a10b22SPatrick Sanan }
99648a10b22SPatrick Sanan 
9971e07b27eSBarry Smith /* -------------------------------------------------------------------------------------*/
9981e07b27eSBarry Smith /*MC
9991e07b27eSBarry Smith    PCTELESCOPE - Runs a KSP solver on a sub-group of processors. MPI processes not in the sub-communicator are idle during the solve.
10001e07b27eSBarry Smith 
10011e07b27eSBarry Smith    Options Database:
1002a04a6428SPatrick 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.
1003a04a6428SPatrick Sanan -  -pc_telescope_ignore_dm  - flag to indicate whether an attached DM should be ignored
1004a04a6428SPatrick Sanan -  -pc_telescope_subcomm_type <interlaced,contiguous> - how to define the reduced communicator. see PetscSubcomm for more.
10051e07b27eSBarry Smith 
10061e07b27eSBarry Smith    Level: advanced
10071e07b27eSBarry Smith 
10081e07b27eSBarry Smith    Notes:
10096fc41876SBarry Smith    The preconditioner is deemed telescopic as it only calls KSPSolve() on a single
10108439623fSPatrick Sanan    sub-communicator, in contrast with PCREDUNDANT which calls KSPSolve() on N sub-communicators.
10118439623fSPatrick Sanan    This means there will be MPI processes which will be idle during the application of this preconditioner.
10126fc41876SBarry Smith 
10131e07b27eSBarry Smith    The default KSP is PREONLY. If a DM is attached to the PC, it is re-partitioned on the sub-communicator.
10141e07b27eSBarry Smith    Both the Bmat operator and the right hand side vector are permuted into the new DOF ordering defined by the re-partitioned DM.
10151e07b27eSBarry Smith    Currently only support for re-partitioning a DMDA is provided.
10168439623fSPatrick Sanan    Any nullspace attached to the original Bmat operator is extracted, re-partitioned and set on the repartitioned Bmat operator.
10171e07b27eSBarry Smith    KSPSetComputeOperators() is not propagated to the sub KSP.
10181e07b27eSBarry Smith    Currently there is no support for the flag -pc_use_amat
10191e07b27eSBarry Smith 
10206fc41876SBarry Smith    Assuming that the parent preconditioner (PC) is defined on a communicator c, this implementation
10218439623fSPatrick Sanan    creates a child sub-communicator (c') containing fewer MPI processes than the original parent preconditioner (PC).
10226fc41876SBarry Smith 
10236fc41876SBarry Smith   Developer Notes:
10246fc41876SBarry Smith    During PCSetup, the B operator is scattered onto c'.
10256fc41876SBarry Smith    Within PCApply, the RHS vector (x) is scattered into a redundant vector, xred (defined on c').
10268439623fSPatrick Sanan    Then, KSPSolve() is executed on the c' communicator.
10276fc41876SBarry Smith 
10286fc41876SBarry Smith    The communicator used within the telescoping preconditioner is defined by a PetscSubcomm using the INTERLACED
1029a04a6428SPatrick 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.
10306fc41876SBarry Smith 
1031005d9f20SPatrick Sanan    The telescoping preconditioner is aware of nullspaces and near nullspaces which are attached to the B operator.
10328439623fSPatrick Sanan    In the case where B has a (near) nullspace attached, the (near) nullspace vectors are extracted from B and mapped into
1033005d9f20SPatrick Sanan    a new (near) nullspace, defined on the sub-communicator, which is attached to B' (the B operator which was scattered to c')
10346fc41876SBarry Smith 
10356fc41876SBarry Smith    The telescoping preconditioner is aware of an attached DM. In the event that the DM is of type DMDA (2D or 3D -
10366fc41876SBarry 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
10376fc41876SBarry Smith    is attached the sub KSPSolve(). The design of telescope is such that it should be possible to extend support
10388439623fSPatrick Sanan    for re-partitioning other to DM's (e.g. DMPLEX). The user can supply a flag to ignore attached DMs.
10396fc41876SBarry Smith 
10406fc41876SBarry Smith    By default, B' is defined by simply fusing rows from different MPI processes
10416fc41876SBarry Smith 
10428439623fSPatrick Sanan    When a DMDA is attached to the parent preconditioner, B' is defined by: (i) performing a symmetric permutation of B
10436fc41876SBarry Smith    into the ordering defined by the DMDA on c', (ii) extracting the local chunks via MatGetSubMatrices(), (iii) fusing the
10446fc41876SBarry Smith    locally (sequential) matrices defined on the ranks common to c and c' into B' using MatCreateMPIMatConcatenateSeqMat()
10456fc41876SBarry Smith 
10468439623fSPatrick Sanan    Limitations/improvements include the following.
10478439623fSPatrick Sanan    VecPlaceArray() could be used within PCApply() to improve efficiency and reduce memory usage.
10486fc41876SBarry Smith 
10496fc41876SBarry Smith    The symmetric permutation used when a DMDA is encountered is performed via explicitly assmbleming a permutation matrix P,
10508439623fSPatrick 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
10518439623fSPatrick Sanan    VecPermute() does not supported for the use case required here. By computing P, one can permute both the operator and RHS in a
10526fc41876SBarry Smith    consistent manner.
10536fc41876SBarry Smith 
10548439623fSPatrick Sanan    Mapping of vectors is performed in the following way.
10558439623fSPatrick 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.
10568439623fSPatrick Sanan    Using the interlaced creation routine, the ranks in c with color = 0 will be rank 0 and 2.
10578439623fSPatrick Sanan    We perform the scatter to the sub-comm in the following way.
10586fc41876SBarry Smith    [1] Given a vector x defined on comm c
10596fc41876SBarry Smith 
10606fc41876SBarry Smith    rank(c) : _________ 0 ______  ________ 1 _______  ________ 2 _____________ ___________ 3 __________
10616fc41876SBarry 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]
10626fc41876SBarry Smith 
10636fc41876SBarry Smith    scatter to xtmp defined also on comm c so that we have the following values
10646fc41876SBarry Smith 
10656fc41876SBarry Smith    rank(c) : ___________________ 0 ________________  _1_  ______________________ 2 _______________________  __3_
10666fc41876SBarry 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] [  ]
10676fc41876SBarry Smith 
10686fc41876SBarry Smith    The entries on rank 1 and 3 (ranks which do not have a color = 0 in c') have no values
10696fc41876SBarry Smith 
10706fc41876SBarry Smith 
10716fc41876SBarry 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'.
10726fc41876SBarry Smith    Ranks 0 and 2 are the only ranks in the subcomm which have a color = 0.
10736fc41876SBarry Smith 
10746fc41876SBarry Smith     rank(c') : ___________________ 0 _______________  ______________________ 1 _____________________
10756fc41876SBarry 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]
10766fc41876SBarry Smith 
10771e07b27eSBarry Smith 
10781e07b27eSBarry Smith   Contributed by Dave May
10791e07b27eSBarry Smith 
1080*bf00f589SPatrick Sanan   Reference:
1081*bf00f589SPatrick Sanan   Dave A. May, Patrick Sanan, Karl Rupp, Matthew G. Knepley, and Barry F. Smith, "Extreme-Scale Multigrid Components within PETSc". 2016. In Proceedings of the Platform for Advanced Scientific Computing Conference (PASC '16). DOI: 10.1145/2929908.2929913
1082*bf00f589SPatrick Sanan 
10836fc41876SBarry Smith .seealso:  PCTelescopeGetKSP(), PCTelescopeGetDM(), PCTelescopeGetReductionFactor(), PCTelescopeSetReductionFactor(), PCTelescopeGetIgnoreDM(), PCTelescopeSetIgnoreDM(), PCREDUNDANT
10841e07b27eSBarry Smith M*/
10851e07b27eSBarry Smith #undef __FUNCT__
10861e07b27eSBarry Smith #define __FUNCT__ "PCCreate_Telescope"
10871e07b27eSBarry Smith PETSC_EXTERN PetscErrorCode PCCreate_Telescope(PC pc)
10881e07b27eSBarry Smith {
10891e07b27eSBarry Smith   PetscErrorCode       ierr;
10901e07b27eSBarry Smith   struct _PC_Telescope *sred;
10911e07b27eSBarry Smith 
10921e07b27eSBarry Smith   PetscFunctionBegin;
10931e07b27eSBarry Smith   ierr = PetscNewLog(pc,&sred);CHKERRQ(ierr);
109448a10b22SPatrick Sanan   sred->subcommtype    = PETSC_SUBCOMM_INTERLACED;
10951e07b27eSBarry Smith   sred->redfactor      = 1;
10961e07b27eSBarry Smith   sred->ignore_dm      = PETSC_FALSE;
10977c5279cbSDave May   sred->ignore_kspcomputeoperators = PETSC_FALSE;
10981e07b27eSBarry Smith   pc->data             = (void*)sred;
10991e07b27eSBarry Smith 
11001e07b27eSBarry Smith   pc->ops->apply           = PCApply_Telescope;
11011e07b27eSBarry Smith   pc->ops->applytranspose  = NULL;
1102f650675bSDave May   pc->ops->applyrichardson = PCApplyRichardson_Telescope;
11031e07b27eSBarry Smith   pc->ops->setup           = PCSetUp_Telescope;
11041e07b27eSBarry Smith   pc->ops->destroy         = PCDestroy_Telescope;
11051e07b27eSBarry Smith   pc->ops->reset           = PCReset_Telescope;
11061e07b27eSBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_Telescope;
11071e07b27eSBarry Smith   pc->ops->view            = PCView_Telescope;
11081e07b27eSBarry Smith 
11091e07b27eSBarry Smith   sred->pctelescope_setup_type              = PCTelescopeSetUp_default;
11101e07b27eSBarry Smith   sred->pctelescope_matcreate_type          = PCTelescopeMatCreate_default;
11111e07b27eSBarry Smith   sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_default;
11121e07b27eSBarry Smith   sred->pctelescope_reset_type              = NULL;
11131e07b27eSBarry Smith 
11141e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetKSP_C",PCTelescopeGetKSP_Telescope);CHKERRQ(ierr);
111548a10b22SPatrick Sanan   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetSubcommType_C",PCTelescopeGetSubcommType_Telescope);CHKERRQ(ierr);
111648a10b22SPatrick Sanan   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetSubcommType_C",PCTelescopeSetSubcommType_Telescope);CHKERRQ(ierr);
11171e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetReductionFactor_C",PCTelescopeGetReductionFactor_Telescope);CHKERRQ(ierr);
11181e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetReductionFactor_C",PCTelescopeSetReductionFactor_Telescope);CHKERRQ(ierr);
11191e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetIgnoreDM_C",PCTelescopeGetIgnoreDM_Telescope);CHKERRQ(ierr);
11201e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetIgnoreDM_C",PCTelescopeSetIgnoreDM_Telescope);CHKERRQ(ierr);
11210ae7c45bSDave May   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetIgnoreKSPComputeOperators_C",PCTelescopeGetIgnoreKSPComputeOperators_Telescope);CHKERRQ(ierr);
11220ae7c45bSDave May   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetIgnoreKSPComputeOperators_C",PCTelescopeSetIgnoreKSPComputeOperators_Telescope);CHKERRQ(ierr);
11231e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetDM_C",PCTelescopeGetDM_Telescope);CHKERRQ(ierr);
11241e07b27eSBarry Smith   PetscFunctionReturn(0);
11251e07b27eSBarry Smith }
1126