xref: /petsc/src/ksp/pc/impls/telescope/telescope.c (revision 41ff1ee92b54847e417a7982df64f6edd9518194)
11e07b27eSBarry Smith 
2120bdd93SDave May #include <petsc/private/matimpl.h>
36fc41876SBarry Smith #include <petsc/private/pcimpl.h>
41e07b27eSBarry Smith #include <petscksp.h> /*I "petscksp.h" I*/
51e07b27eSBarry Smith #include <petscdm.h> /*I "petscdm.h" I*/
6575a0592SBarry Smith #include "../src/ksp/pc/impls/telescope/telescope.h"
71e07b27eSBarry Smith 
81e07b27eSBarry Smith /*
91e07b27eSBarry Smith  PCTelescopeSetUp_default()
101e07b27eSBarry Smith  PCTelescopeMatCreate_default()
111e07b27eSBarry Smith 
121e07b27eSBarry Smith  default
131e07b27eSBarry Smith 
141e07b27eSBarry Smith  // scatter in
151e07b27eSBarry Smith  x(comm) -> xtmp(comm)
161e07b27eSBarry Smith 
171e07b27eSBarry Smith  xred(subcomm) <- xtmp
181e07b27eSBarry Smith  yred(subcomm)
191e07b27eSBarry Smith 
201e07b27eSBarry Smith  yred(subcomm) --> xtmp
211e07b27eSBarry Smith 
221e07b27eSBarry Smith  // scatter out
231e07b27eSBarry Smith  xtmp(comm) -> y(comm)
241e07b27eSBarry Smith */
251e07b27eSBarry Smith 
261e07b27eSBarry Smith PetscBool isActiveRank(PetscSubcomm scomm)
271e07b27eSBarry Smith {
281e07b27eSBarry Smith   if (scomm->color == 0) { return PETSC_TRUE; }
291e07b27eSBarry Smith   else { return PETSC_FALSE; }
301e07b27eSBarry Smith }
311e07b27eSBarry Smith 
321e07b27eSBarry Smith #undef __FUNCT__
331e07b27eSBarry Smith #define __FUNCT__ "private_PCTelescopeGetSubDM"
341e07b27eSBarry Smith DM private_PCTelescopeGetSubDM(PC_Telescope sred)
351e07b27eSBarry Smith {
36c6a0d831SBarry Smith   DM subdm = NULL;
371e07b27eSBarry Smith 
381e07b27eSBarry Smith   if (!isActiveRank(sred->psubcomm)) { subdm = NULL; }
391e07b27eSBarry Smith   else {
401e07b27eSBarry Smith     switch (sred->sr_type) {
411e07b27eSBarry Smith     case TELESCOPE_DEFAULT: subdm = NULL;
421e07b27eSBarry Smith       break;
431e07b27eSBarry Smith     case TELESCOPE_DMDA:    subdm = ((PC_Telescope_DMDACtx*)sred->dm_ctx)->dmrepart;
441e07b27eSBarry Smith       break;
451e07b27eSBarry Smith     case TELESCOPE_DMPLEX:  subdm = NULL;
461e07b27eSBarry Smith       break;
471e07b27eSBarry Smith     }
481e07b27eSBarry Smith   }
491e07b27eSBarry Smith   return(subdm);
501e07b27eSBarry Smith }
511e07b27eSBarry Smith 
521e07b27eSBarry Smith #undef __FUNCT__
531e07b27eSBarry Smith #define __FUNCT__ "PCTelescopeSetUp_default"
541e07b27eSBarry Smith PetscErrorCode PCTelescopeSetUp_default(PC pc,PC_Telescope sred)
551e07b27eSBarry Smith {
561e07b27eSBarry Smith   PetscErrorCode ierr;
571e07b27eSBarry Smith   PetscInt       m,M,bs,st,ed;
581e07b27eSBarry Smith   Vec            x,xred,yred,xtmp;
591e07b27eSBarry Smith   Mat            B;
601e07b27eSBarry Smith   MPI_Comm       comm,subcomm;
611e07b27eSBarry Smith   VecScatter     scatter;
621e07b27eSBarry Smith   IS             isin;
631e07b27eSBarry Smith 
641e07b27eSBarry Smith   PetscFunctionBegin;
651e07b27eSBarry Smith   ierr = PetscInfo(pc,"PCTelescope: setup (default)\n");CHKERRQ(ierr);
661e07b27eSBarry Smith   comm = PetscSubcommParent(sred->psubcomm);
671e07b27eSBarry Smith   subcomm = PetscSubcommChild(sred->psubcomm);
681e07b27eSBarry Smith 
691e07b27eSBarry Smith   ierr = PCGetOperators(pc,NULL,&B);CHKERRQ(ierr);
701e07b27eSBarry Smith   ierr = MatGetSize(B,&M,NULL);CHKERRQ(ierr);
711e07b27eSBarry Smith   ierr = MatGetBlockSize(B,&bs);CHKERRQ(ierr);
721e07b27eSBarry Smith   ierr = MatCreateVecs(B,&x,NULL);CHKERRQ(ierr);
731e07b27eSBarry Smith 
741e07b27eSBarry Smith   xred = NULL;
753ac26c5eSBarry Smith   m    = 0;
761e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
771e07b27eSBarry Smith     ierr = VecCreate(subcomm,&xred);CHKERRQ(ierr);
781e07b27eSBarry Smith     ierr = VecSetSizes(xred,PETSC_DECIDE,M);CHKERRQ(ierr);
791e07b27eSBarry Smith     ierr = VecSetBlockSize(xred,bs);CHKERRQ(ierr);
801e07b27eSBarry Smith     ierr = VecSetFromOptions(xred);CHKERRQ(ierr);
81ca43db0aSBarry Smith     ierr = VecGetLocalSize(xred,&m);CHKERRQ(ierr);
821e07b27eSBarry Smith   }
831e07b27eSBarry Smith 
841e07b27eSBarry Smith   yred = NULL;
851e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
861e07b27eSBarry Smith     ierr = VecDuplicate(xred,&yred);CHKERRQ(ierr);
871e07b27eSBarry Smith   }
881e07b27eSBarry Smith 
891e07b27eSBarry Smith   ierr = VecCreate(comm,&xtmp);CHKERRQ(ierr);
901e07b27eSBarry Smith   ierr = VecSetSizes(xtmp,m,PETSC_DECIDE);CHKERRQ(ierr);
911e07b27eSBarry Smith   ierr = VecSetBlockSize(xtmp,bs);CHKERRQ(ierr);
921e07b27eSBarry Smith   ierr = VecSetType(xtmp,((PetscObject)x)->type_name);CHKERRQ(ierr);
931e07b27eSBarry Smith 
941e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
951e07b27eSBarry Smith     ierr = VecGetOwnershipRange(xred,&st,&ed);CHKERRQ(ierr);
961e07b27eSBarry Smith     ierr = ISCreateStride(comm,(ed-st),st,1,&isin);CHKERRQ(ierr);
971e07b27eSBarry Smith   } else {
981e07b27eSBarry Smith     ierr = VecGetOwnershipRange(x,&st,&ed);CHKERRQ(ierr);
993ac26c5eSBarry Smith     ierr = ISCreateStride(comm,0,st,1,&isin);CHKERRQ(ierr);
1001e07b27eSBarry Smith   }
1011e07b27eSBarry Smith   ierr = ISSetBlockSize(isin,bs);CHKERRQ(ierr);
1021e07b27eSBarry Smith 
1031e07b27eSBarry Smith   ierr = VecScatterCreate(x,isin,xtmp,NULL,&scatter);CHKERRQ(ierr);
1041e07b27eSBarry Smith 
1051e07b27eSBarry Smith   sred->isin    = isin;
1061e07b27eSBarry Smith   sred->scatter = scatter;
1071e07b27eSBarry Smith   sred->xred    = xred;
1081e07b27eSBarry Smith   sred->yred    = yred;
1091e07b27eSBarry Smith   sred->xtmp    = xtmp;
1101e07b27eSBarry Smith   ierr = VecDestroy(&x);CHKERRQ(ierr);
1111e07b27eSBarry Smith   PetscFunctionReturn(0);
1121e07b27eSBarry Smith }
1131e07b27eSBarry Smith 
1141e07b27eSBarry Smith #undef __FUNCT__
1151e07b27eSBarry Smith #define __FUNCT__ "PCTelescopeMatCreate_default"
1161e07b27eSBarry Smith PetscErrorCode PCTelescopeMatCreate_default(PC pc,PC_Telescope sred,MatReuse reuse,Mat *A)
1171e07b27eSBarry Smith {
1181e07b27eSBarry Smith   PetscErrorCode ierr;
1191e07b27eSBarry Smith   MPI_Comm       comm,subcomm;
1201e07b27eSBarry Smith   Mat            Bred,B;
1211e07b27eSBarry Smith   PetscInt       nr,nc;
1221e07b27eSBarry Smith   IS             isrow,iscol;
1231e07b27eSBarry Smith   Mat            Blocal,*_Blocal;
1241e07b27eSBarry Smith 
1251e07b27eSBarry Smith   PetscFunctionBegin;
1261e07b27eSBarry Smith   ierr = PetscInfo(pc,"PCTelescope: updating the redundant preconditioned operator (default)\n");CHKERRQ(ierr);
1271e07b27eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
1281e07b27eSBarry Smith   subcomm = PetscSubcommChild(sred->psubcomm);
1291e07b27eSBarry Smith   ierr = PCGetOperators(pc,NULL,&B);CHKERRQ(ierr);
1301e07b27eSBarry Smith   ierr = MatGetSize(B,&nr,&nc);CHKERRQ(ierr);
1311e07b27eSBarry Smith   isrow = sred->isin;
1321e07b27eSBarry Smith   ierr = ISCreateStride(comm,nc,0,1,&iscol);CHKERRQ(ierr);
1331e07b27eSBarry Smith   ierr = MatGetSubMatrices(B,1,&isrow,&iscol,MAT_INITIAL_MATRIX,&_Blocal);CHKERRQ(ierr);
1341e07b27eSBarry Smith   Blocal = *_Blocal;
1351e07b27eSBarry Smith   ierr = PetscFree(_Blocal);CHKERRQ(ierr);
1361e07b27eSBarry Smith   Bred = NULL;
1371e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
1381e07b27eSBarry Smith     PetscInt mm;
1391e07b27eSBarry Smith 
1401e07b27eSBarry Smith     if (reuse != MAT_INITIAL_MATRIX) { Bred = *A; }
1411e07b27eSBarry Smith 
1421e07b27eSBarry Smith     ierr = MatGetSize(Blocal,&mm,NULL);CHKERRQ(ierr);
1431e07b27eSBarry Smith     ierr = MatCreateMPIMatConcatenateSeqMat(subcomm,Blocal,mm,reuse,&Bred);CHKERRQ(ierr);
1441e07b27eSBarry Smith   }
1451e07b27eSBarry Smith   *A = Bred;
1461e07b27eSBarry Smith   ierr = ISDestroy(&iscol);CHKERRQ(ierr);
1471e07b27eSBarry Smith   ierr = MatDestroy(&Blocal);CHKERRQ(ierr);
1481e07b27eSBarry Smith   PetscFunctionReturn(0);
1491e07b27eSBarry Smith }
1501e07b27eSBarry Smith 
1511e07b27eSBarry Smith #undef __FUNCT__
1521e07b27eSBarry Smith #define __FUNCT__ "PCTelescopeMatNullSpaceCreate_default"
153d8b9d5b7SPatrick Sanan static PetscErrorCode PCTelescopeMatNullSpaceCreate_default(PC pc,PC_Telescope sred,Mat sub_mat,PetscBool near)
1541e07b27eSBarry Smith {
1551e07b27eSBarry Smith   PetscErrorCode   ierr;
1561e07b27eSBarry Smith   MatNullSpace     nullspace,sub_nullspace;
1571e07b27eSBarry Smith   Mat              A,B;
1581e07b27eSBarry Smith   PetscBool        has_const;
159a947c41eSDave May   PetscInt         i,k,n = 0;
1601e07b27eSBarry Smith   const Vec        *vecs;
161c41e779fSDave May   Vec              *sub_vecs = NULL;
1621e07b27eSBarry Smith   MPI_Comm         subcomm;
1631e07b27eSBarry Smith 
1641e07b27eSBarry Smith   PetscFunctionBegin;
1651e07b27eSBarry Smith   ierr = PCGetOperators(pc,&A,&B);CHKERRQ(ierr);
166d8b9d5b7SPatrick Sanan 
167d8b9d5b7SPatrick Sanan   /* If the "near" flag was provided, instead operate on the near nullspace */
168d8b9d5b7SPatrick Sanan   if (near) {
169d8b9d5b7SPatrick Sanan     ierr = MatGetNearNullSpace(B,&nullspace);CHKERRQ(ierr);
170d8b9d5b7SPatrick Sanan   } else {
1711e07b27eSBarry Smith     ierr = MatGetNullSpace(B,&nullspace);CHKERRQ(ierr);
172d8b9d5b7SPatrick Sanan   }
173a947c41eSDave May   if (!nullspace) PetscFunctionReturn(0);
1741e07b27eSBarry Smith 
175d8b9d5b7SPatrick Sanan   if (near) {
176d8b9d5b7SPatrick Sanan     ierr = PetscInfo(pc,"PCTelescope: generating near nullspace (default)\n");CHKERRQ(ierr);
177d8b9d5b7SPatrick Sanan   } else {
1781e07b27eSBarry Smith     ierr = PetscInfo(pc,"PCTelescope: generating nullspace (default)\n");CHKERRQ(ierr);
179d8b9d5b7SPatrick Sanan   }
1801e07b27eSBarry Smith   subcomm = PetscSubcommChild(sred->psubcomm);
1811e07b27eSBarry Smith   ierr = MatNullSpaceGetVecs(nullspace,&has_const,&n,&vecs);CHKERRQ(ierr);
1821e07b27eSBarry Smith 
1831e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
184e3acf2f7SBarry Smith     if (n) {
185e3acf2f7SBarry Smith       ierr = VecDuplicateVecs(sred->xred,n,&sub_vecs);CHKERRQ(ierr);
1861e07b27eSBarry Smith     }
1871e07b27eSBarry Smith   }
1881e07b27eSBarry Smith 
1891e07b27eSBarry Smith   /* copy entries */
1901e07b27eSBarry Smith   for (k=0; k<n; k++) {
1911e07b27eSBarry Smith     const PetscScalar *x_array;
1921e07b27eSBarry Smith     PetscScalar       *LA_sub_vec;
19313c30530SDave May     PetscInt          st,ed;
1941e07b27eSBarry Smith 
1951e07b27eSBarry Smith     /* pull in vector x->xtmp */
1961e07b27eSBarry Smith     ierr = VecScatterBegin(sred->scatter,vecs[k],sred->xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1971e07b27eSBarry Smith     ierr = VecScatterEnd(sred->scatter,vecs[k],sred->xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19847856c66SBarry Smith     if (sub_vecs) {
199a04a6428SPatrick Sanan       /* copy vector entries into xred */
2001e07b27eSBarry Smith       ierr = VecGetArrayRead(sred->xtmp,&x_array);CHKERRQ(ierr);
201ea2b237eSDave May       if (sub_vecs[k]) {
2021e07b27eSBarry Smith         ierr = VecGetOwnershipRange(sub_vecs[k],&st,&ed);CHKERRQ(ierr);
2031e07b27eSBarry Smith         ierr = VecGetArray(sub_vecs[k],&LA_sub_vec);CHKERRQ(ierr);
2041e07b27eSBarry Smith         for (i=0; i<ed-st; i++) {
2051e07b27eSBarry Smith           LA_sub_vec[i] = x_array[i];
2061e07b27eSBarry Smith         }
2071e07b27eSBarry Smith         ierr = VecRestoreArray(sub_vecs[k],&LA_sub_vec);CHKERRQ(ierr);
2081e07b27eSBarry Smith       }
2091e07b27eSBarry Smith       ierr = VecRestoreArrayRead(sred->xtmp,&x_array);CHKERRQ(ierr);
2101e07b27eSBarry Smith     }
21147856c66SBarry Smith   }
2121e07b27eSBarry Smith 
2131e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
214d8b9d5b7SPatrick Sanan     /* create new (near) nullspace for redundant object */
2151e07b27eSBarry Smith     ierr = MatNullSpaceCreate(subcomm,has_const,n,sub_vecs,&sub_nullspace);CHKERRQ(ierr);
216d8b9d5b7SPatrick Sanan     if (nullspace->remove) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Propagation of custom remove callbacks not supported when propagating (near) nullspaces with PCTelescope");
217d8b9d5b7SPatrick 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");
218120bdd93SDave May 
219d8b9d5b7SPatrick Sanan     /* attach redundant (near) nullspace to Bred */
220d8b9d5b7SPatrick Sanan     if (near) {
221d8b9d5b7SPatrick Sanan       ierr = MatSetNearNullSpace(sub_mat,sub_nullspace);CHKERRQ(ierr);
222d8b9d5b7SPatrick Sanan     } else {
2231e07b27eSBarry Smith       ierr = MatSetNullSpace(sub_mat,sub_nullspace);CHKERRQ(ierr);
224d8b9d5b7SPatrick Sanan     }
225e3acf2f7SBarry Smith     ierr = VecDestroyVecs(n,&sub_vecs);CHKERRQ(ierr);
226*41ff1ee9SPatrick Sanan     ierr = MatNullSpaceDestroy(&sub_nullspace);CHKERRQ(ierr);
2271e07b27eSBarry Smith   }
2281e07b27eSBarry Smith   PetscFunctionReturn(0);
2291e07b27eSBarry Smith }
2301e07b27eSBarry Smith 
2311e07b27eSBarry Smith #undef __FUNCT__
2321e07b27eSBarry Smith #define __FUNCT__ "PCView_Telescope"
2331e07b27eSBarry Smith static PetscErrorCode PCView_Telescope(PC pc,PetscViewer viewer)
2341e07b27eSBarry Smith {
2351e07b27eSBarry Smith   PC_Telescope     sred = (PC_Telescope)pc->data;
2361e07b27eSBarry Smith   PetscErrorCode   ierr;
2371e07b27eSBarry Smith   PetscBool        iascii,isstring;
2381e07b27eSBarry Smith   PetscViewer      subviewer;
2391e07b27eSBarry Smith 
2401e07b27eSBarry Smith   PetscFunctionBegin;
2411e07b27eSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
2421e07b27eSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr);
2431e07b27eSBarry Smith   if (iascii) {
2441e07b27eSBarry Smith     if (!sred->psubcomm) {
2451e07b27eSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Telescope: preconditioner not yet setup\n");CHKERRQ(ierr);
2461e07b27eSBarry Smith     } else {
2471e07b27eSBarry Smith       MPI_Comm    comm,subcomm;
2481e07b27eSBarry Smith       PetscMPIInt comm_size,subcomm_size;
2491e07b27eSBarry Smith       DM          dm,subdm;
2501e07b27eSBarry Smith 
2511e07b27eSBarry Smith       ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
2521e07b27eSBarry Smith       subdm = private_PCTelescopeGetSubDM(sred);
2531e07b27eSBarry Smith       comm = PetscSubcommParent(sred->psubcomm);
2541e07b27eSBarry Smith       subcomm = PetscSubcommChild(sred->psubcomm);
2551e07b27eSBarry Smith       ierr = MPI_Comm_size(comm,&comm_size);CHKERRQ(ierr);
2561e07b27eSBarry Smith       ierr = MPI_Comm_size(subcomm,&subcomm_size);CHKERRQ(ierr);
2571e07b27eSBarry Smith 
2581e07b27eSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Telescope: parent comm size reduction factor = %D\n",sred->redfactor);CHKERRQ(ierr);
2591e07b27eSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Telescope: comm_size = %d , subcomm_size = %d\n",(int)comm_size,(int)subcomm_size);CHKERRQ(ierr);
26048a10b22SPatrick Sanan       switch (sred->subcommtype) {
26148a10b22SPatrick Sanan         case PETSC_SUBCOMM_INTERLACED :
26248a10b22SPatrick Sanan           ierr = PetscViewerASCIIPrintf(viewer,"  Telescope: subcomm type: interlaced\n",sred->subcommtype);CHKERRQ(ierr);
26348a10b22SPatrick Sanan           break;
26448a10b22SPatrick Sanan         case PETSC_SUBCOMM_CONTIGUOUS :
26548a10b22SPatrick Sanan           ierr = PetscViewerASCIIPrintf(viewer,"  Telescope: subcomm type: contiguous\n",sred->subcommtype);CHKERRQ(ierr);
26648a10b22SPatrick Sanan           break;
26748a10b22SPatrick Sanan         default :
26848a10b22SPatrick Sanan           SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"General subcomm type not supported by PCTelescope");
26948a10b22SPatrick Sanan       }
2701e07b27eSBarry Smith       ierr = PetscViewerGetSubViewer(viewer,subcomm,&subviewer);CHKERRQ(ierr);
2711e07b27eSBarry Smith       if (isActiveRank(sred->psubcomm)) {
2721e07b27eSBarry Smith         ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr);
2731e07b27eSBarry Smith 
2741e07b27eSBarry Smith         if (dm && sred->ignore_dm) {
2751e07b27eSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: ignoring DM\n");CHKERRQ(ierr);
2761e07b27eSBarry Smith         }
2777c5279cbSDave May         if (sred->ignore_kspcomputeoperators) {
2787c5279cbSDave May           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: ignoring KSPComputeOperators\n");CHKERRQ(ierr);
2797c5279cbSDave May         }
2801e07b27eSBarry Smith         switch (sred->sr_type) {
2811e07b27eSBarry Smith         case TELESCOPE_DEFAULT:
2821e07b27eSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: using default setup\n");CHKERRQ(ierr);
2831e07b27eSBarry Smith           break;
2841e07b27eSBarry Smith         case TELESCOPE_DMDA:
2851e07b27eSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: DMDA detected\n");CHKERRQ(ierr);
2861e07b27eSBarry Smith           ierr = DMView_DMDAShort(subdm,subviewer);CHKERRQ(ierr);
2871e07b27eSBarry Smith           break;
2881e07b27eSBarry Smith         case TELESCOPE_DMPLEX:
2891e07b27eSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: DMPLEX detected\n");CHKERRQ(ierr);
2901e07b27eSBarry Smith           break;
2911e07b27eSBarry Smith         }
2921e07b27eSBarry Smith 
2931e07b27eSBarry Smith         ierr = KSPView(sred->ksp,subviewer);CHKERRQ(ierr);
2941e07b27eSBarry Smith         ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr);
2951e07b27eSBarry Smith       }
2961e07b27eSBarry Smith       ierr = PetscViewerRestoreSubViewer(viewer,subcomm,&subviewer);CHKERRQ(ierr);
2971e07b27eSBarry Smith     }
2981e07b27eSBarry Smith   }
2991e07b27eSBarry Smith   PetscFunctionReturn(0);
3001e07b27eSBarry Smith }
3011e07b27eSBarry Smith 
3021e07b27eSBarry Smith #undef __FUNCT__
3031e07b27eSBarry Smith #define __FUNCT__ "PCSetUp_Telescope"
3041e07b27eSBarry Smith static PetscErrorCode PCSetUp_Telescope(PC pc)
3051e07b27eSBarry Smith {
3061e07b27eSBarry Smith   PC_Telescope      sred = (PC_Telescope)pc->data;
3071e07b27eSBarry Smith   PetscErrorCode    ierr;
308bd49479cSSatish Balay   MPI_Comm          comm,subcomm=0;
3091e07b27eSBarry Smith   PCTelescopeType   sr_type;
3101e07b27eSBarry Smith 
3111e07b27eSBarry Smith   PetscFunctionBegin;
3121e07b27eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
3131e07b27eSBarry Smith 
3141e07b27eSBarry Smith   /* subcomm definition */
3151e07b27eSBarry Smith   if (!pc->setupcalled) {
3161e07b27eSBarry Smith     if (!sred->psubcomm) {
3171e07b27eSBarry Smith       ierr = PetscSubcommCreate(comm,&sred->psubcomm);CHKERRQ(ierr);
3181e07b27eSBarry Smith       ierr = PetscSubcommSetNumber(sred->psubcomm,sred->redfactor);CHKERRQ(ierr);
31948a10b22SPatrick Sanan       ierr = PetscSubcommSetType(sred->psubcomm,sred->subcommtype);CHKERRQ(ierr);
3201e07b27eSBarry Smith       ierr = PetscLogObjectMemory((PetscObject)pc,sizeof(PetscSubcomm));CHKERRQ(ierr);
3211e07b27eSBarry Smith     }
3221e07b27eSBarry Smith   }
3230f6f40a7SSatish Balay   subcomm = PetscSubcommChild(sred->psubcomm);
3241e07b27eSBarry Smith 
3251e07b27eSBarry Smith   /* internal KSP */
3261e07b27eSBarry Smith   if (!pc->setupcalled) {
3271e07b27eSBarry Smith     const char *prefix;
3281e07b27eSBarry Smith 
3291e07b27eSBarry Smith     if (isActiveRank(sred->psubcomm)) {
3301e07b27eSBarry Smith       ierr = KSPCreate(subcomm,&sred->ksp);CHKERRQ(ierr);
3311e07b27eSBarry Smith       ierr = KSPSetErrorIfNotConverged(sred->ksp,pc->erroriffailure);CHKERRQ(ierr);
3321e07b27eSBarry Smith       ierr = PetscObjectIncrementTabLevel((PetscObject)sred->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
3331e07b27eSBarry Smith       ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)sred->ksp);CHKERRQ(ierr);
3341e07b27eSBarry Smith       ierr = KSPSetType(sred->ksp,KSPPREONLY);CHKERRQ(ierr);
3351e07b27eSBarry Smith       ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
3361e07b27eSBarry Smith       ierr = KSPSetOptionsPrefix(sred->ksp,prefix);CHKERRQ(ierr);
3371e07b27eSBarry Smith       ierr = KSPAppendOptionsPrefix(sred->ksp,"telescope_");CHKERRQ(ierr);
3381e07b27eSBarry Smith     }
3391e07b27eSBarry Smith   }
3401e07b27eSBarry Smith   /* Determine type of setup/update */
3411e07b27eSBarry Smith   if (!pc->setupcalled) {
3421e07b27eSBarry Smith     PetscBool has_dm,same;
3431e07b27eSBarry Smith     DM        dm;
3441e07b27eSBarry Smith 
3451e07b27eSBarry Smith     sr_type = TELESCOPE_DEFAULT;
3461e07b27eSBarry Smith     has_dm = PETSC_FALSE;
3471e07b27eSBarry Smith     ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
3481e07b27eSBarry Smith     if (dm) { has_dm = PETSC_TRUE; }
3491e07b27eSBarry Smith     if (has_dm) {
3501e07b27eSBarry Smith       /* check for dmda */
3511e07b27eSBarry Smith       ierr = PetscObjectTypeCompare((PetscObject)dm,DMDA,&same);CHKERRQ(ierr);
3521e07b27eSBarry Smith       if (same) {
3531e07b27eSBarry Smith         ierr = PetscInfo(pc,"PCTelescope: found DMDA\n");CHKERRQ(ierr);
3541e07b27eSBarry Smith         sr_type = TELESCOPE_DMDA;
3551e07b27eSBarry Smith       }
3561e07b27eSBarry Smith       /* check for dmplex */
3571e07b27eSBarry Smith       ierr = PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&same);CHKERRQ(ierr);
3581e07b27eSBarry Smith       if (same) {
3591e07b27eSBarry Smith         PetscInfo(pc,"PCTelescope: found DMPLEX\n");
3601e07b27eSBarry Smith         sr_type = TELESCOPE_DMPLEX;
3611e07b27eSBarry Smith       }
3621e07b27eSBarry Smith     }
3631e07b27eSBarry Smith 
3641e07b27eSBarry Smith     if (sred->ignore_dm) {
3651e07b27eSBarry Smith       PetscInfo(pc,"PCTelescope: ignore DM\n");
3661e07b27eSBarry Smith       sr_type = TELESCOPE_DEFAULT;
3671e07b27eSBarry Smith     }
3681e07b27eSBarry Smith     sred->sr_type = sr_type;
3691e07b27eSBarry Smith   } else {
3701e07b27eSBarry Smith     sr_type = sred->sr_type;
3711e07b27eSBarry Smith   }
3721e07b27eSBarry Smith 
373d8b9d5b7SPatrick Sanan   /* set function pointers for repartition setup, matrix creation/update, matrix (near) nullspace, and reset functionality */
3741e07b27eSBarry Smith   switch (sr_type) {
3751e07b27eSBarry Smith   case TELESCOPE_DEFAULT:
3761e07b27eSBarry Smith     sred->pctelescope_setup_type              = PCTelescopeSetUp_default;
3771e07b27eSBarry Smith     sred->pctelescope_matcreate_type          = PCTelescopeMatCreate_default;
3781e07b27eSBarry Smith     sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_default;
3791e07b27eSBarry Smith     sred->pctelescope_reset_type              = NULL;
3801e07b27eSBarry Smith     break;
3811e07b27eSBarry Smith   case TELESCOPE_DMDA:
3821e07b27eSBarry Smith     pc->ops->apply                            = PCApply_Telescope_dmda;
383f650675bSDave May     pc->ops->applyrichardson                  = PCApplyRichardson_Telescope_dmda;
3841e07b27eSBarry Smith     sred->pctelescope_setup_type              = PCTelescopeSetUp_dmda;
3851e07b27eSBarry Smith     sred->pctelescope_matcreate_type          = PCTelescopeMatCreate_dmda;
3861e07b27eSBarry Smith     sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_dmda;
3871e07b27eSBarry Smith     sred->pctelescope_reset_type              = PCReset_Telescope_dmda;
3881e07b27eSBarry Smith     break;
389d8b9d5b7SPatrick Sanan   case TELESCOPE_DMPLEX: SETERRQ(comm,PETSC_ERR_SUP,"Support for DMPLEX is currently not available");
3901e07b27eSBarry Smith     break;
391a04a6428SPatrick Sanan   default: SETERRQ(comm,PETSC_ERR_SUP,"Only support for repartitioning DMDA is provided");
3921e07b27eSBarry Smith     break;
3931e07b27eSBarry Smith   }
3941e07b27eSBarry Smith 
3951e07b27eSBarry Smith   /* setup */
3961e07b27eSBarry Smith   if (sred->pctelescope_setup_type) {
3971e07b27eSBarry Smith     ierr = sred->pctelescope_setup_type(pc,sred);CHKERRQ(ierr);
3981e07b27eSBarry Smith   }
3991e07b27eSBarry Smith   /* update */
4001e07b27eSBarry Smith   if (!pc->setupcalled) {
4011e07b27eSBarry Smith     if (sred->pctelescope_matcreate_type) {
4021e07b27eSBarry Smith       ierr = sred->pctelescope_matcreate_type(pc,sred,MAT_INITIAL_MATRIX,&sred->Bred);CHKERRQ(ierr);
4031e07b27eSBarry Smith     }
4041e07b27eSBarry Smith     if (sred->pctelescope_matnullspacecreate_type) {
405d8b9d5b7SPatrick Sanan       /* Propagate attached nullspace and near nullspace, if they exist */
406d8b9d5b7SPatrick Sanan       ierr = sred->pctelescope_matnullspacecreate_type(pc,sred,sred->Bred,PETSC_TRUE);CHKERRQ(ierr);
407d8b9d5b7SPatrick Sanan       ierr = sred->pctelescope_matnullspacecreate_type(pc,sred,sred->Bred,PETSC_FALSE);CHKERRQ(ierr);
4081e07b27eSBarry Smith     }
4091e07b27eSBarry Smith   } else {
4101e07b27eSBarry Smith     if (sred->pctelescope_matcreate_type) {
4111e07b27eSBarry Smith       ierr = sred->pctelescope_matcreate_type(pc,sred,MAT_REUSE_MATRIX,&sred->Bred);CHKERRQ(ierr);
4121e07b27eSBarry Smith     }
4131e07b27eSBarry Smith   }
4141e07b27eSBarry Smith 
4151e07b27eSBarry Smith   /* common - no construction */
4161e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
4171e07b27eSBarry Smith     ierr = KSPSetOperators(sred->ksp,sred->Bred,sred->Bred);CHKERRQ(ierr);
4181e07b27eSBarry Smith     if (pc->setfromoptionscalled && !pc->setupcalled){
4191e07b27eSBarry Smith       ierr = KSPSetFromOptions(sred->ksp);CHKERRQ(ierr);
4201e07b27eSBarry Smith     }
4211e07b27eSBarry Smith   }
4221e07b27eSBarry Smith   PetscFunctionReturn(0);
4231e07b27eSBarry Smith }
4241e07b27eSBarry Smith 
4251e07b27eSBarry Smith #undef __FUNCT__
4261e07b27eSBarry Smith #define __FUNCT__ "PCApply_Telescope"
4271e07b27eSBarry Smith static PetscErrorCode PCApply_Telescope(PC pc,Vec x,Vec y)
4281e07b27eSBarry Smith {
4291e07b27eSBarry Smith   PC_Telescope      sred = (PC_Telescope)pc->data;
4301e07b27eSBarry Smith   PetscErrorCode    ierr;
4311e07b27eSBarry Smith   Vec               xtmp,xred,yred;
43213c30530SDave May   PetscInt          i,st,ed;
4331e07b27eSBarry Smith   VecScatter        scatter;
4341e07b27eSBarry Smith   PetscScalar       *array;
4351e07b27eSBarry Smith   const PetscScalar *x_array;
4361e07b27eSBarry Smith 
4371e07b27eSBarry Smith   PetscFunctionBegin;
4381e07b27eSBarry Smith   xtmp    = sred->xtmp;
4391e07b27eSBarry Smith   scatter = sred->scatter;
4401e07b27eSBarry Smith   xred    = sred->xred;
4411e07b27eSBarry Smith   yred    = sred->yred;
4421e07b27eSBarry Smith 
4431e07b27eSBarry Smith   /* pull in vector x->xtmp */
4441e07b27eSBarry Smith   ierr = VecScatterBegin(scatter,x,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4451e07b27eSBarry Smith   ierr = VecScatterEnd(scatter,x,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4461e07b27eSBarry Smith 
4471e07b27eSBarry Smith   /* copy vector entires into xred */
4481e07b27eSBarry Smith   ierr = VecGetArrayRead(xtmp,&x_array);CHKERRQ(ierr);
4491e07b27eSBarry Smith   if (xred) {
4501e07b27eSBarry Smith     PetscScalar *LA_xred;
4511e07b27eSBarry Smith     ierr = VecGetOwnershipRange(xred,&st,&ed);CHKERRQ(ierr);
4521e07b27eSBarry Smith     ierr = VecGetArray(xred,&LA_xred);CHKERRQ(ierr);
4531e07b27eSBarry Smith     for (i=0; i<ed-st; i++) {
4541e07b27eSBarry Smith       LA_xred[i] = x_array[i];
4551e07b27eSBarry Smith     }
4561e07b27eSBarry Smith     ierr = VecRestoreArray(xred,&LA_xred);CHKERRQ(ierr);
4571e07b27eSBarry Smith   }
4581e07b27eSBarry Smith   ierr = VecRestoreArrayRead(xtmp,&x_array);CHKERRQ(ierr);
4591e07b27eSBarry Smith   /* solve */
4601e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
4611e07b27eSBarry Smith     ierr = KSPSolve(sred->ksp,xred,yred);CHKERRQ(ierr);
4621e07b27eSBarry Smith   }
4631e07b27eSBarry Smith   /* return vector */
4641e07b27eSBarry Smith   ierr = VecGetArray(xtmp,&array);CHKERRQ(ierr);
4651e07b27eSBarry Smith   if (yred) {
4661e07b27eSBarry Smith     const PetscScalar *LA_yred;
4671e07b27eSBarry Smith     ierr = VecGetOwnershipRange(yred,&st,&ed);CHKERRQ(ierr);
4681e07b27eSBarry Smith     ierr = VecGetArrayRead(yred,&LA_yred);CHKERRQ(ierr);
4691e07b27eSBarry Smith     for (i=0; i<ed-st; i++) {
4701e07b27eSBarry Smith       array[i] = LA_yred[i];
4711e07b27eSBarry Smith     }
4721e07b27eSBarry Smith     ierr = VecRestoreArrayRead(yred,&LA_yred);CHKERRQ(ierr);
4731e07b27eSBarry Smith   }
4741e07b27eSBarry Smith   ierr = VecRestoreArray(xtmp,&array);CHKERRQ(ierr);
4751e07b27eSBarry Smith   ierr = VecScatterBegin(scatter,xtmp,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4761e07b27eSBarry Smith   ierr = VecScatterEnd(scatter,xtmp,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4771e07b27eSBarry Smith   PetscFunctionReturn(0);
4781e07b27eSBarry Smith }
4791e07b27eSBarry Smith 
4801e07b27eSBarry Smith #undef __FUNCT__
481f650675bSDave May #define __FUNCT__ "PCApplyRichardson_Telescope"
482f650675bSDave 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)
483f650675bSDave May {
484f650675bSDave May   PC_Telescope      sred = (PC_Telescope)pc->data;
485f650675bSDave May   PetscErrorCode    ierr;
486a1d91a28SDave May   Vec               xtmp,yred;
487f650675bSDave May   PetscInt          i,st,ed;
488f650675bSDave May   VecScatter        scatter;
489f650675bSDave May   const PetscScalar *x_array;
490f650675bSDave May   PetscBool         default_init_guess_value;
491f650675bSDave May 
492f650675bSDave May   PetscFunctionBegin;
493f650675bSDave May   xtmp    = sred->xtmp;
494f650675bSDave May   scatter = sred->scatter;
495f650675bSDave May   yred    = sred->yred;
496f650675bSDave May 
497f650675bSDave May   if (its > 1) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCApplyRichardson_Telescope only supports max_it = 1");
498f650675bSDave May   *reason = (PCRichardsonConvergedReason)0;
499f650675bSDave May 
500f650675bSDave May   if (!zeroguess) {
501f650675bSDave May     ierr = PetscInfo(pc,"PCTelescope: Scattering y for non-zero initial guess\n");CHKERRQ(ierr);
502f650675bSDave May     /* pull in vector y->xtmp */
503f650675bSDave May     ierr = VecScatterBegin(scatter,y,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
504f650675bSDave May     ierr = VecScatterEnd(scatter,y,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
505f650675bSDave May 
506f650675bSDave May     /* copy vector entires into xred */
507f650675bSDave May     ierr = VecGetArrayRead(xtmp,&x_array);CHKERRQ(ierr);
508f650675bSDave May     if (yred) {
509f650675bSDave May       PetscScalar *LA_yred;
510f650675bSDave May       ierr = VecGetOwnershipRange(yred,&st,&ed);CHKERRQ(ierr);
511f650675bSDave May       ierr = VecGetArray(yred,&LA_yred);CHKERRQ(ierr);
512f650675bSDave May       for (i=0; i<ed-st; i++) {
513f650675bSDave May         LA_yred[i] = x_array[i];
514f650675bSDave May       }
515f650675bSDave May       ierr = VecRestoreArray(yred,&LA_yred);CHKERRQ(ierr);
516f650675bSDave May     }
517f650675bSDave May     ierr = VecRestoreArrayRead(xtmp,&x_array);CHKERRQ(ierr);
518f650675bSDave May   }
519f650675bSDave May 
520f650675bSDave May   if (isActiveRank(sred->psubcomm)) {
521f650675bSDave May     ierr = KSPGetInitialGuessNonzero(sred->ksp,&default_init_guess_value);CHKERRQ(ierr);
522f650675bSDave May     if (!zeroguess) ierr = KSPSetInitialGuessNonzero(sred->ksp,PETSC_TRUE);CHKERRQ(ierr);
523f650675bSDave May   }
524f650675bSDave May 
525f650675bSDave May   ierr = PCApply_Telescope(pc,x,y);CHKERRQ(ierr);
526f650675bSDave May 
527f650675bSDave May   if (isActiveRank(sred->psubcomm)) {
528f650675bSDave May     ierr = KSPSetInitialGuessNonzero(sred->ksp,default_init_guess_value);CHKERRQ(ierr);
529f650675bSDave May   }
530f650675bSDave May 
531f650675bSDave May   if (!*reason) *reason = PCRICHARDSON_CONVERGED_ITS;
532f650675bSDave May   *outits = 1;
533f650675bSDave May   PetscFunctionReturn(0);
534f650675bSDave May }
535f650675bSDave May 
536f650675bSDave May #undef __FUNCT__
5371e07b27eSBarry Smith #define __FUNCT__ "PCReset_Telescope"
5381e07b27eSBarry Smith static PetscErrorCode PCReset_Telescope(PC pc)
5391e07b27eSBarry Smith {
5401e07b27eSBarry Smith   PC_Telescope   sred = (PC_Telescope)pc->data;
5411e07b27eSBarry Smith   PetscErrorCode ierr;
5421e07b27eSBarry Smith 
5431e07b27eSBarry Smith   ierr = ISDestroy(&sred->isin);CHKERRQ(ierr);
5441e07b27eSBarry Smith   ierr = VecScatterDestroy(&sred->scatter);CHKERRQ(ierr);
545e3acf2f7SBarry Smith   ierr = VecDestroy(&sred->xred);CHKERRQ(ierr);
546e3acf2f7SBarry Smith   ierr = VecDestroy(&sred->yred);CHKERRQ(ierr);
547e3acf2f7SBarry Smith   ierr = VecDestroy(&sred->xtmp);CHKERRQ(ierr);
548e3acf2f7SBarry Smith   ierr = MatDestroy(&sred->Bred);CHKERRQ(ierr);
549e3acf2f7SBarry Smith   ierr = KSPReset(sred->ksp);CHKERRQ(ierr);
5501e07b27eSBarry Smith   if (sred->pctelescope_reset_type) {
5511e07b27eSBarry Smith     ierr = sred->pctelescope_reset_type(pc);CHKERRQ(ierr);
5521e07b27eSBarry Smith   }
5531e07b27eSBarry Smith   PetscFunctionReturn(0);
5541e07b27eSBarry Smith }
5551e07b27eSBarry Smith 
5561e07b27eSBarry Smith #undef __FUNCT__
5571e07b27eSBarry Smith #define __FUNCT__ "PCDestroy_Telescope"
5581e07b27eSBarry Smith static PetscErrorCode PCDestroy_Telescope(PC pc)
5591e07b27eSBarry Smith {
5601e07b27eSBarry Smith   PC_Telescope     sred = (PC_Telescope)pc->data;
5611e07b27eSBarry Smith   PetscErrorCode   ierr;
5621e07b27eSBarry Smith 
5631e07b27eSBarry Smith   PetscFunctionBegin;
5641e07b27eSBarry Smith   ierr = PCReset_Telescope(pc);CHKERRQ(ierr);
565e3acf2f7SBarry Smith   ierr = KSPDestroy(&sred->ksp);CHKERRQ(ierr);
5661e07b27eSBarry Smith   ierr = PetscSubcommDestroy(&sred->psubcomm);CHKERRQ(ierr);
567e3acf2f7SBarry Smith   ierr = PetscFree(sred->dm_ctx);CHKERRQ(ierr);
568e3acf2f7SBarry Smith   ierr = PetscFree(pc->data);CHKERRQ(ierr);
5691e07b27eSBarry Smith   PetscFunctionReturn(0);
5701e07b27eSBarry Smith }
5711e07b27eSBarry Smith 
5721e07b27eSBarry Smith #undef __FUNCT__
5731e07b27eSBarry Smith #define __FUNCT__ "PCSetFromOptions_Telescope"
5744416b707SBarry Smith static PetscErrorCode PCSetFromOptions_Telescope(PetscOptionItems *PetscOptionsObject,PC pc)
5751e07b27eSBarry Smith {
5761e07b27eSBarry Smith   PC_Telescope     sred = (PC_Telescope)pc->data;
5771e07b27eSBarry Smith   PetscErrorCode   ierr;
5781e07b27eSBarry Smith   MPI_Comm         comm;
5791e07b27eSBarry Smith   PetscMPIInt      size;
58048a10b22SPatrick Sanan   PetscBool        flg;
58148a10b22SPatrick Sanan   PetscSubcommType subcommtype;
5821e07b27eSBarry Smith 
5831e07b27eSBarry Smith   PetscFunctionBegin;
5841e07b27eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
5851e07b27eSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
5861e07b27eSBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"Telescope options");CHKERRQ(ierr);
58748a10b22SPatrick Sanan   ierr = PetscOptionsEnum("-pc_telescope_subcomm_type","Subcomm type (interlaced or contiguous)","PCTelescopeSetSubcommType",PetscSubcommTypes,(PetscEnum)sred->subcommtype,(PetscEnum*)&subcommtype,&flg);CHKERRQ(ierr);
58848a10b22SPatrick Sanan   if (flg) {
58948a10b22SPatrick Sanan     ierr = PCTelescopeSetSubcommType(pc,subcommtype);CHKERRQ(ierr);
59048a10b22SPatrick Sanan   }
5911e07b27eSBarry Smith   ierr = PetscOptionsInt("-pc_telescope_reduction_factor","Factor to reduce comm size by","PCTelescopeSetReductionFactor",sred->redfactor,&sred->redfactor,0);CHKERRQ(ierr);
5921e07b27eSBarry Smith   if (sred->redfactor > size) SETERRQ(comm,PETSC_ERR_ARG_WRONG,"-pc_telescope_reduction_factor <= comm size");
5931e07b27eSBarry Smith   ierr = PetscOptionsBool("-pc_telescope_ignore_dm","Ignore any DM attached to the PC","PCTelescopeSetIgnoreDM",sred->ignore_dm,&sred->ignore_dm,0);CHKERRQ(ierr);
5947c5279cbSDave May   ierr = PetscOptionsBool("-pc_telescope_ignore_kspcomputeoperators","Ignore method used to compute A","PCTelescopeSetIgnoreKSPComputeOperators",sred->ignore_kspcomputeoperators,&sred->ignore_kspcomputeoperators,0);CHKERRQ(ierr);
5951e07b27eSBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
5961e07b27eSBarry Smith   PetscFunctionReturn(0);
5971e07b27eSBarry Smith }
5981e07b27eSBarry Smith 
5991e07b27eSBarry Smith /* PC simplementation specific API's */
6001e07b27eSBarry Smith 
60148a10b22SPatrick Sanan #undef __FUNCT__
60248a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeGetKSP_Telescope"
6031e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetKSP_Telescope(PC pc,KSP *ksp)
6041e07b27eSBarry Smith {
6051e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
606bd49479cSSatish Balay   PetscFunctionBegin;
6071e07b27eSBarry Smith   if (ksp) *ksp = red->ksp;
608bd49479cSSatish Balay   PetscFunctionReturn(0);
6091e07b27eSBarry Smith }
6101e07b27eSBarry Smith 
61148a10b22SPatrick Sanan #undef __FUNCT__
61248a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeGetSubcommType_Telescope"
61348a10b22SPatrick Sanan static PetscErrorCode PCTelescopeGetSubcommType_Telescope(PC pc,PetscSubcommType *subcommtype)
61448a10b22SPatrick Sanan {
61548a10b22SPatrick Sanan   PC_Telescope red = (PC_Telescope)pc->data;
61648a10b22SPatrick Sanan   PetscFunctionBegin;
61748a10b22SPatrick Sanan   if (subcommtype) *subcommtype = red->subcommtype;
61848a10b22SPatrick Sanan   PetscFunctionReturn(0);
61948a10b22SPatrick Sanan }
62048a10b22SPatrick Sanan 
62148a10b22SPatrick Sanan #undef __FUNCT__
62248a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeSetSubcommType_Telescope"
62348a10b22SPatrick Sanan static PetscErrorCode PCTelescopeSetSubcommType_Telescope(PC pc,PetscSubcommType subcommtype)
62448a10b22SPatrick Sanan {
62548a10b22SPatrick Sanan   PC_Telescope     red = (PC_Telescope)pc->data;
62648a10b22SPatrick Sanan 
62748a10b22SPatrick Sanan   PetscFunctionBegin;
62848a10b22SPatrick 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.");
62948a10b22SPatrick Sanan   red->subcommtype = subcommtype;
63048a10b22SPatrick Sanan   PetscFunctionReturn(0);
63148a10b22SPatrick Sanan }
63248a10b22SPatrick Sanan 
63348a10b22SPatrick Sanan #undef __FUNCT__
63448a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeGetReductionFactor_Telescope"
6351e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetReductionFactor_Telescope(PC pc,PetscInt *fact)
6361e07b27eSBarry Smith {
6371e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
638bd49479cSSatish Balay   PetscFunctionBegin;
6391e07b27eSBarry Smith   if (fact) *fact = red->redfactor;
640bd49479cSSatish Balay   PetscFunctionReturn(0);
6411e07b27eSBarry Smith }
6421e07b27eSBarry Smith 
64348a10b22SPatrick Sanan #undef __FUNCT__
64448a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeSetReductionFactor_Telescope"
6451e07b27eSBarry Smith static PetscErrorCode PCTelescopeSetReductionFactor_Telescope(PC pc,PetscInt fact)
6461e07b27eSBarry Smith {
6471e07b27eSBarry Smith   PC_Telescope     red = (PC_Telescope)pc->data;
6481e07b27eSBarry Smith   PetscMPIInt      size;
6491e07b27eSBarry Smith   PetscErrorCode   ierr;
6501e07b27eSBarry Smith 
651bd49479cSSatish Balay   PetscFunctionBegin;
6521e07b27eSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
6531e07b27eSBarry Smith   if (fact <= 0) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Reduction factor of telescoping PC %D must be positive",fact);
6541e07b27eSBarry Smith   if (fact > size) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Reduction factor of telescoping PC %D must be <= comm.size",fact);
6551e07b27eSBarry Smith   red->redfactor = fact;
656bd49479cSSatish Balay   PetscFunctionReturn(0);
6571e07b27eSBarry Smith }
6581e07b27eSBarry Smith 
65948a10b22SPatrick Sanan #undef __FUNCT__
66048a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeGetIgnoreDM_Telescope"
6611e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetIgnoreDM_Telescope(PC pc,PetscBool *v)
6621e07b27eSBarry Smith {
6631e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
664bd49479cSSatish Balay   PetscFunctionBegin;
6651e07b27eSBarry Smith   if (v) *v = red->ignore_dm;
666bd49479cSSatish Balay   PetscFunctionReturn(0);
6671e07b27eSBarry Smith }
66848a10b22SPatrick Sanan 
66948a10b22SPatrick Sanan #undef __FUNCT__
67048a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeSetIgnoreDM_Telescope"
6711e07b27eSBarry Smith static PetscErrorCode PCTelescopeSetIgnoreDM_Telescope(PC pc,PetscBool v)
6721e07b27eSBarry Smith {
6731e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
674bd49479cSSatish Balay   PetscFunctionBegin;
6751e07b27eSBarry Smith   red->ignore_dm = v;
676bd49479cSSatish Balay   PetscFunctionReturn(0);
6771e07b27eSBarry Smith }
6781e07b27eSBarry Smith 
67948a10b22SPatrick Sanan #undef __FUNCT__
68048a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeGetIgnoreKSPComputeOperators_Telescope"
6810ae7c45bSDave May static PetscErrorCode PCTelescopeGetIgnoreKSPComputeOperators_Telescope(PC pc,PetscBool *v)
6820ae7c45bSDave May {
6830ae7c45bSDave May   PC_Telescope red = (PC_Telescope)pc->data;
6840ae7c45bSDave May   PetscFunctionBegin;
6850ae7c45bSDave May   if (v) *v = red->ignore_kspcomputeoperators;
6860ae7c45bSDave May   PetscFunctionReturn(0);
6870ae7c45bSDave May }
68848a10b22SPatrick Sanan 
68948a10b22SPatrick Sanan #undef __FUNCT__
69048a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeSetIgnoreKSPComputeOperators_Telescope"
6910ae7c45bSDave May static PetscErrorCode PCTelescopeSetIgnoreKSPComputeOperators_Telescope(PC pc,PetscBool v)
6920ae7c45bSDave May {
6930ae7c45bSDave May   PC_Telescope red = (PC_Telescope)pc->data;
6940ae7c45bSDave May   PetscFunctionBegin;
6950ae7c45bSDave May   red->ignore_kspcomputeoperators = v;
6960ae7c45bSDave May   PetscFunctionReturn(0);
6970ae7c45bSDave May }
6980ae7c45bSDave May 
69948a10b22SPatrick Sanan #undef __FUNCT__
70048a10b22SPatrick Sanan #define __FUNCT__ "PCTelescopeGetDM_Telescope"
7011e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetDM_Telescope(PC pc,DM *dm)
7021e07b27eSBarry Smith {
7031e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
704bd49479cSSatish Balay   PetscFunctionBegin;
7051e07b27eSBarry Smith   *dm = private_PCTelescopeGetSubDM(red);
706bd49479cSSatish Balay   PetscFunctionReturn(0);
7071e07b27eSBarry Smith }
7081e07b27eSBarry Smith 
7090f43ea10SBarry Smith #undef __FUNCT__
7100f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeGetKSP"
7111e07b27eSBarry Smith /*@
7121e07b27eSBarry Smith  PCTelescopeGetKSP - Gets the KSP created by the telescoping PC.
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 .  subksp - the KSP defined the smaller set of processes
7211e07b27eSBarry Smith 
7221e07b27eSBarry Smith  Level: advanced
7231e07b27eSBarry Smith 
7241e07b27eSBarry Smith .keywords: PC, telescopting solve
7251e07b27eSBarry Smith @*/
7261e07b27eSBarry Smith PetscErrorCode PCTelescopeGetKSP(PC pc,KSP *subksp)
7271e07b27eSBarry Smith {
728bd49479cSSatish Balay   PetscErrorCode ierr;
729bd49479cSSatish Balay   PetscFunctionBegin;
730163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetKSP_C",(PC,KSP*),(pc,subksp));CHKERRQ(ierr);
731bd49479cSSatish Balay   PetscFunctionReturn(0);
7321e07b27eSBarry Smith }
7331e07b27eSBarry Smith 
7340f43ea10SBarry Smith #undef __FUNCT__
7350f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeGetReductionFactor"
7361e07b27eSBarry Smith /*@
7371e07b27eSBarry Smith  PCTelescopeGetReductionFactor - Gets the factor by which the original number of processes has been reduced by.
7381e07b27eSBarry Smith 
7391e07b27eSBarry Smith  Not Collective
7401e07b27eSBarry Smith 
7411e07b27eSBarry Smith  Input Parameter:
7421e07b27eSBarry Smith .  pc - the preconditioner context
7431e07b27eSBarry Smith 
7441e07b27eSBarry Smith  Output Parameter:
7451e07b27eSBarry Smith .  fact - the reduction factor
7461e07b27eSBarry Smith 
7471e07b27eSBarry Smith  Level: advanced
7481e07b27eSBarry Smith 
7491e07b27eSBarry Smith .keywords: PC, telescoping solve
7501e07b27eSBarry Smith @*/
7511e07b27eSBarry Smith PetscErrorCode PCTelescopeGetReductionFactor(PC pc,PetscInt *fact)
7521e07b27eSBarry Smith {
753bd49479cSSatish Balay   PetscErrorCode ierr;
754bd49479cSSatish Balay   PetscFunctionBegin;
755163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetReductionFactor_C",(PC,PetscInt*),(pc,fact));CHKERRQ(ierr);
756bd49479cSSatish Balay   PetscFunctionReturn(0);
7571e07b27eSBarry Smith }
7581e07b27eSBarry Smith 
7590f43ea10SBarry Smith #undef __FUNCT__
7600f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeSetReductionFactor"
7611e07b27eSBarry Smith /*@
7621e07b27eSBarry Smith  PCTelescopeSetReductionFactor - Sets the factor by which the original number of processes has been reduced by.
7631e07b27eSBarry Smith 
7641e07b27eSBarry Smith  Not Collective
7651e07b27eSBarry Smith 
7661e07b27eSBarry Smith  Input Parameter:
7671e07b27eSBarry Smith .  pc - the preconditioner context
7681e07b27eSBarry Smith 
7691e07b27eSBarry Smith  Output Parameter:
7701e07b27eSBarry Smith .  fact - the reduction factor
7711e07b27eSBarry Smith 
7721e07b27eSBarry Smith  Level: advanced
7731e07b27eSBarry Smith 
7741e07b27eSBarry Smith .keywords: PC, telescoping solve
7751e07b27eSBarry Smith @*/
7761e07b27eSBarry Smith PetscErrorCode PCTelescopeSetReductionFactor(PC pc,PetscInt fact)
7771e07b27eSBarry Smith {
778bd49479cSSatish Balay   PetscErrorCode ierr;
779bd49479cSSatish Balay   PetscFunctionBegin;
780bd49479cSSatish Balay   ierr = PetscTryMethod(pc,"PCTelescopeSetReductionFactor_C",(PC,PetscInt),(pc,fact));CHKERRQ(ierr);
781bd49479cSSatish Balay   PetscFunctionReturn(0);
7821e07b27eSBarry Smith }
7831e07b27eSBarry Smith 
7840f43ea10SBarry Smith #undef __FUNCT__
7850f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeGetIgnoreDM"
7861e07b27eSBarry Smith /*@
7871e07b27eSBarry Smith  PCTelescopeGetIgnoreDM - Get the flag indicating if any DM attached to the PC will be used.
7881e07b27eSBarry Smith 
7891e07b27eSBarry Smith  Not Collective
7901e07b27eSBarry Smith 
7911e07b27eSBarry Smith  Input Parameter:
7921e07b27eSBarry Smith .  pc - the preconditioner context
7931e07b27eSBarry Smith 
7941e07b27eSBarry Smith  Output Parameter:
7951e07b27eSBarry Smith .  v - the flag
7961e07b27eSBarry Smith 
7971e07b27eSBarry Smith  Level: advanced
7981e07b27eSBarry Smith 
7991e07b27eSBarry Smith .keywords: PC, telescoping solve
8001e07b27eSBarry Smith @*/
8011e07b27eSBarry Smith PetscErrorCode PCTelescopeGetIgnoreDM(PC pc,PetscBool *v)
8021e07b27eSBarry Smith {
803bd49479cSSatish Balay   PetscErrorCode ierr;
804bd49479cSSatish Balay   PetscFunctionBegin;
805163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetIgnoreDM_C",(PC,PetscBool*),(pc,v));CHKERRQ(ierr);
806bd49479cSSatish Balay   PetscFunctionReturn(0);
8071e07b27eSBarry Smith }
8081e07b27eSBarry Smith 
8090f43ea10SBarry Smith #undef __FUNCT__
8100f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeSetIgnoreDM"
8111e07b27eSBarry Smith /*@
8121e07b27eSBarry Smith  PCTelescopeSetIgnoreDM - Set a flag to ignore any DM attached to the PC.
8131e07b27eSBarry Smith 
8141e07b27eSBarry Smith  Not Collective
8151e07b27eSBarry Smith 
8161e07b27eSBarry Smith  Input Parameter:
8171e07b27eSBarry Smith .  pc - the preconditioner context
8181e07b27eSBarry Smith 
8191e07b27eSBarry Smith  Output Parameter:
8201e07b27eSBarry Smith .  v - Use PETSC_TRUE to ignore any DM
8211e07b27eSBarry Smith 
8221e07b27eSBarry Smith  Level: advanced
8231e07b27eSBarry Smith 
8241e07b27eSBarry Smith .keywords: PC, telescoping solve
8251e07b27eSBarry Smith @*/
826bfd6bcc6SSatish Balay PetscErrorCode PCTelescopeSetIgnoreDM(PC pc,PetscBool v)
8271e07b27eSBarry Smith {
828bd49479cSSatish Balay   PetscErrorCode ierr;
829bd49479cSSatish Balay   PetscFunctionBegin;
830bd49479cSSatish Balay   ierr = PetscTryMethod(pc,"PCTelescopeSetIgnoreDM_C",(PC,PetscBool),(pc,v));CHKERRQ(ierr);
831bd49479cSSatish Balay   PetscFunctionReturn(0);
8321e07b27eSBarry Smith }
8331e07b27eSBarry Smith 
8340f43ea10SBarry Smith #undef __FUNCT__
8350f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeGetIgnoreKSPComputeOperators"
8361e07b27eSBarry Smith /*@
8370ae7c45bSDave May  PCTelescopeGetIgnoreKSPComputeOperators - Get the flag indicating if KSPComputeOperators will be used.
8380ae7c45bSDave May 
8390ae7c45bSDave May  Not Collective
8400ae7c45bSDave May 
8410ae7c45bSDave May  Input Parameter:
8420ae7c45bSDave May .  pc - the preconditioner context
8430ae7c45bSDave May 
8440ae7c45bSDave May  Output Parameter:
8450ae7c45bSDave May .  v - the flag
8460ae7c45bSDave May 
8470ae7c45bSDave May  Level: advanced
8480ae7c45bSDave May 
8490ae7c45bSDave May .keywords: PC, telescoping solve
8500ae7c45bSDave May @*/
8510ae7c45bSDave May PetscErrorCode PCTelescopeGetIgnoreKSPComputeOperators(PC pc,PetscBool *v)
8520ae7c45bSDave May {
8530ae7c45bSDave May   PetscErrorCode ierr;
8540ae7c45bSDave May   PetscFunctionBegin;
855163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetIgnoreKSPComputeOperators_C",(PC,PetscBool*),(pc,v));CHKERRQ(ierr);
8560ae7c45bSDave May   PetscFunctionReturn(0);
8570ae7c45bSDave May }
8580ae7c45bSDave May 
8590f43ea10SBarry Smith #undef __FUNCT__
8600f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeSetIgnoreKSPComputeOperators"
8610ae7c45bSDave May /*@
8620ae7c45bSDave May  PCTelescopeSetIgnoreKSPComputeOperators - Set a flag to ignore KSPComputeOperators.
8630ae7c45bSDave May 
8640ae7c45bSDave May  Not Collective
8650ae7c45bSDave May 
8660ae7c45bSDave May  Input Parameter:
8670ae7c45bSDave May .  pc - the preconditioner context
8680ae7c45bSDave May 
8690ae7c45bSDave May  Output Parameter:
870a954d8f4SDave May .  v - Use PETSC_TRUE to ignore the method (if defined) set via KSPSetComputeOperators on pc
8710ae7c45bSDave May 
8720ae7c45bSDave May  Level: advanced
8730ae7c45bSDave May 
8740ae7c45bSDave May .keywords: PC, telescoping solve
8750ae7c45bSDave May @*/
8760ae7c45bSDave May PetscErrorCode PCTelescopeSetIgnoreKSPComputeOperators(PC pc,PetscBool v)
8770ae7c45bSDave May {
8780ae7c45bSDave May   PetscErrorCode ierr;
8790ae7c45bSDave May   PetscFunctionBegin;
8800ae7c45bSDave May   ierr = PetscTryMethod(pc,"PCTelescopeSetIgnoreKSPComputeOperators_C",(PC,PetscBool),(pc,v));CHKERRQ(ierr);
8810ae7c45bSDave May   PetscFunctionReturn(0);
8820ae7c45bSDave May }
8830ae7c45bSDave May 
8840f43ea10SBarry Smith #undef __FUNCT__
8850f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeGetDM"
8860ae7c45bSDave May /*@
8871e07b27eSBarry Smith  PCTelescopeGetDM - Get the re-partitioned DM attached to the sub KSP.
8881e07b27eSBarry Smith 
8891e07b27eSBarry Smith  Not Collective
8901e07b27eSBarry Smith 
8911e07b27eSBarry Smith  Input Parameter:
8921e07b27eSBarry Smith .  pc - the preconditioner context
8931e07b27eSBarry Smith 
8941e07b27eSBarry Smith  Output Parameter:
8951e07b27eSBarry Smith .  subdm - The re-partitioned DM
8961e07b27eSBarry Smith 
8971e07b27eSBarry Smith  Level: advanced
8981e07b27eSBarry Smith 
8991e07b27eSBarry Smith .keywords: PC, telescoping solve
9001e07b27eSBarry Smith @*/
9011e07b27eSBarry Smith PetscErrorCode PCTelescopeGetDM(PC pc,DM *subdm)
9021e07b27eSBarry Smith {
903bd49479cSSatish Balay   PetscErrorCode ierr;
904bd49479cSSatish Balay   PetscFunctionBegin;
905163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetDM_C",(PC,DM*),(pc,subdm));CHKERRQ(ierr);
906bd49479cSSatish Balay   PetscFunctionReturn(0);
9071e07b27eSBarry Smith }
9081e07b27eSBarry Smith 
9090f43ea10SBarry Smith #undef __FUNCT__
9100f43ea10SBarry Smith #define __FUNCT__ "PCTelescopeSetSubcommType"
91148a10b22SPatrick Sanan /*@
91248a10b22SPatrick Sanan  PCTelescopeSetSubcommType - set subcommunicator type (interlaced or contiguous)
91348a10b22SPatrick Sanan 
91448a10b22SPatrick Sanan  Logically Collective
91548a10b22SPatrick Sanan 
91648a10b22SPatrick Sanan  Input Parameter:
9171dae98e4SBarry Smith +  pc - the preconditioner context
9181dae98e4SBarry Smith -  subcommtype - the subcommunicator type (see PetscSubcommType)
91948a10b22SPatrick Sanan 
92048a10b22SPatrick Sanan  Level: advanced
92148a10b22SPatrick Sanan 
92248a10b22SPatrick Sanan .keywords: PC, telescoping solve
92348a10b22SPatrick Sanan 
92448a10b22SPatrick Sanan .seealso: PetscSubcommType, PetscSubcomm, PCTELESCOPE
92548a10b22SPatrick Sanan @*/
92648a10b22SPatrick Sanan PetscErrorCode PCTelescopeSetSubcommType(PC pc, PetscSubcommType subcommtype)
92748a10b22SPatrick Sanan {
92848a10b22SPatrick Sanan   PetscErrorCode ierr;
92948a10b22SPatrick Sanan   PetscFunctionBegin;
93048a10b22SPatrick Sanan   ierr = PetscTryMethod(pc,"PCTelescopeSetSubcommType_C",(PC,PetscSubcommType),(pc,subcommtype));CHKERRQ(ierr);
93148a10b22SPatrick Sanan   PetscFunctionReturn(0);
93248a10b22SPatrick Sanan }
93348a10b22SPatrick Sanan 
9340f43ea10SBarry Smith #undef __FUNCT__
9351dae98e4SBarry Smith #define __FUNCT__ "PCTelescopeGetSubcommType"
93648a10b22SPatrick Sanan /*@
93748a10b22SPatrick Sanan  PCTelescopeGetSubcommType - Get the subcommunicator type (interlaced or contiguous)
93848a10b22SPatrick Sanan 
93948a10b22SPatrick Sanan  Not Collective
94048a10b22SPatrick Sanan 
94148a10b22SPatrick Sanan  Input Parameter:
94248a10b22SPatrick Sanan .  pc - the preconditioner context
94348a10b22SPatrick Sanan 
94448a10b22SPatrick Sanan  Output Parameter:
94548a10b22SPatrick Sanan .  subcommtype - the subcommunicator type (see PetscSubcommType)
94648a10b22SPatrick Sanan 
94748a10b22SPatrick Sanan  Level: advanced
94848a10b22SPatrick Sanan 
94948a10b22SPatrick Sanan .keywords: PC, telescoping solve
95048a10b22SPatrick Sanan 
9511dae98e4SBarry Smith .seealso: PetscSubcomm, PetscSubcommType, PCTELESCOPE
95248a10b22SPatrick Sanan @*/
9531dae98e4SBarry Smith PetscErrorCode PCTelescopeGetSubcommType(PC pc, PetscSubcommType *subcommtype)
95448a10b22SPatrick Sanan {
95548a10b22SPatrick Sanan   PetscErrorCode ierr;
95648a10b22SPatrick Sanan   PetscFunctionBegin;
95748a10b22SPatrick Sanan   ierr = PetscUseMethod(pc,"PCTelescopeGetSubcommType_C",(PC,PetscSubcommType*),(pc,subcommtype));CHKERRQ(ierr);
95848a10b22SPatrick Sanan   PetscFunctionReturn(0);
95948a10b22SPatrick Sanan }
96048a10b22SPatrick Sanan 
9611e07b27eSBarry Smith /* -------------------------------------------------------------------------------------*/
9621e07b27eSBarry Smith /*MC
9631e07b27eSBarry Smith    PCTELESCOPE - Runs a KSP solver on a sub-group of processors. MPI processes not in the sub-communicator are idle during the solve.
9641e07b27eSBarry Smith 
9651e07b27eSBarry Smith    Options Database:
966a04a6428SPatrick 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.
967a04a6428SPatrick Sanan -  -pc_telescope_ignore_dm  - flag to indicate whether an attached DM should be ignored
968a04a6428SPatrick Sanan -  -pc_telescope_subcomm_type <interlaced,contiguous> - how to define the reduced communicator. see PetscSubcomm for more.
9691e07b27eSBarry Smith 
9701e07b27eSBarry Smith    Level: advanced
9711e07b27eSBarry Smith 
9721e07b27eSBarry Smith    Notes:
9736fc41876SBarry Smith    The preconditioner is deemed telescopic as it only calls KSPSolve() on a single
9748439623fSPatrick Sanan    sub-communicator, in contrast with PCREDUNDANT which calls KSPSolve() on N sub-communicators.
9758439623fSPatrick Sanan    This means there will be MPI processes which will be idle during the application of this preconditioner.
9766fc41876SBarry Smith 
9771e07b27eSBarry Smith    The default KSP is PREONLY. If a DM is attached to the PC, it is re-partitioned on the sub-communicator.
9781e07b27eSBarry Smith    Both the Bmat operator and the right hand side vector are permuted into the new DOF ordering defined by the re-partitioned DM.
9791e07b27eSBarry Smith    Currently only support for re-partitioning a DMDA is provided.
9808439623fSPatrick Sanan    Any nullspace attached to the original Bmat operator is extracted, re-partitioned and set on the repartitioned Bmat operator.
9811e07b27eSBarry Smith    KSPSetComputeOperators() is not propagated to the sub KSP.
9821e07b27eSBarry Smith    Currently there is no support for the flag -pc_use_amat
9831e07b27eSBarry Smith 
9846fc41876SBarry Smith    Assuming that the parent preconditioner (PC) is defined on a communicator c, this implementation
9858439623fSPatrick Sanan    creates a child sub-communicator (c') containing fewer MPI processes than the original parent preconditioner (PC).
9866fc41876SBarry Smith 
9876fc41876SBarry Smith   Developer Notes:
9886fc41876SBarry Smith    During PCSetup, the B operator is scattered onto c'.
9896fc41876SBarry Smith    Within PCApply, the RHS vector (x) is scattered into a redundant vector, xred (defined on c').
9908439623fSPatrick Sanan    Then, KSPSolve() is executed on the c' communicator.
9916fc41876SBarry Smith 
9926fc41876SBarry Smith    The communicator used within the telescoping preconditioner is defined by a PetscSubcomm using the INTERLACED
993a04a6428SPatrick 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.
9946fc41876SBarry Smith 
995005d9f20SPatrick Sanan    The telescoping preconditioner is aware of nullspaces and near nullspaces which are attached to the B operator.
9968439623fSPatrick Sanan    In the case where B has a (near) nullspace attached, the (near) nullspace vectors are extracted from B and mapped into
997005d9f20SPatrick Sanan    a new (near) nullspace, defined on the sub-communicator, which is attached to B' (the B operator which was scattered to c')
9986fc41876SBarry Smith 
9996fc41876SBarry Smith    The telescoping preconditioner is aware of an attached DM. In the event that the DM is of type DMDA (2D or 3D -
10006fc41876SBarry 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
10016fc41876SBarry Smith    is attached the sub KSPSolve(). The design of telescope is such that it should be possible to extend support
10028439623fSPatrick Sanan    for re-partitioning other to DM's (e.g. DMPLEX). The user can supply a flag to ignore attached DMs.
10036fc41876SBarry Smith 
10046fc41876SBarry Smith    By default, B' is defined by simply fusing rows from different MPI processes
10056fc41876SBarry Smith 
10068439623fSPatrick Sanan    When a DMDA is attached to the parent preconditioner, B' is defined by: (i) performing a symmetric permutation of B
10076fc41876SBarry Smith    into the ordering defined by the DMDA on c', (ii) extracting the local chunks via MatGetSubMatrices(), (iii) fusing the
10086fc41876SBarry Smith    locally (sequential) matrices defined on the ranks common to c and c' into B' using MatCreateMPIMatConcatenateSeqMat()
10096fc41876SBarry Smith 
10108439623fSPatrick Sanan    Limitations/improvements include the following.
10118439623fSPatrick Sanan    VecPlaceArray() could be used within PCApply() to improve efficiency and reduce memory usage.
10126fc41876SBarry Smith 
10136fc41876SBarry Smith    The symmetric permutation used when a DMDA is encountered is performed via explicitly assmbleming a permutation matrix P,
10148439623fSPatrick 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
10158439623fSPatrick Sanan    VecPermute() does not supported for the use case required here. By computing P, one can permute both the operator and RHS in a
10166fc41876SBarry Smith    consistent manner.
10176fc41876SBarry Smith 
10188439623fSPatrick Sanan    Mapping of vectors is performed in the following way.
10198439623fSPatrick 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.
10208439623fSPatrick Sanan    Using the interlaced creation routine, the ranks in c with color = 0 will be rank 0 and 2.
10218439623fSPatrick Sanan    We perform the scatter to the sub-comm in the following way.
10226fc41876SBarry Smith    [1] Given a vector x defined on comm c
10236fc41876SBarry Smith 
10246fc41876SBarry Smith    rank(c) : _________ 0 ______  ________ 1 _______  ________ 2 _____________ ___________ 3 __________
10256fc41876SBarry 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]
10266fc41876SBarry Smith 
10276fc41876SBarry Smith    scatter to xtmp defined also on comm c so that we have the following values
10286fc41876SBarry Smith 
10296fc41876SBarry Smith    rank(c) : ___________________ 0 ________________  _1_  ______________________ 2 _______________________  __3_
10306fc41876SBarry 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] [  ]
10316fc41876SBarry Smith 
10326fc41876SBarry Smith    The entries on rank 1 and 3 (ranks which do not have a color = 0 in c') have no values
10336fc41876SBarry Smith 
10346fc41876SBarry Smith 
10356fc41876SBarry 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'.
10366fc41876SBarry Smith    Ranks 0 and 2 are the only ranks in the subcomm which have a color = 0.
10376fc41876SBarry Smith 
10386fc41876SBarry Smith     rank(c') : ___________________ 0 _______________  ______________________ 1 _____________________
10396fc41876SBarry 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]
10406fc41876SBarry Smith 
10411e07b27eSBarry Smith 
10421e07b27eSBarry Smith   Contributed by Dave May
10431e07b27eSBarry Smith 
10446fc41876SBarry Smith .seealso:  PCTelescopeGetKSP(), PCTelescopeGetDM(), PCTelescopeGetReductionFactor(), PCTelescopeSetReductionFactor(), PCTelescopeGetIgnoreDM(), PCTelescopeSetIgnoreDM(), PCREDUNDANT
10451e07b27eSBarry Smith M*/
10461e07b27eSBarry Smith #undef __FUNCT__
10471e07b27eSBarry Smith #define __FUNCT__ "PCCreate_Telescope"
10481e07b27eSBarry Smith PETSC_EXTERN PetscErrorCode PCCreate_Telescope(PC pc)
10491e07b27eSBarry Smith {
10501e07b27eSBarry Smith   PetscErrorCode       ierr;
10511e07b27eSBarry Smith   struct _PC_Telescope *sred;
10521e07b27eSBarry Smith 
10531e07b27eSBarry Smith   PetscFunctionBegin;
10541e07b27eSBarry Smith   ierr = PetscNewLog(pc,&sred);CHKERRQ(ierr);
105548a10b22SPatrick Sanan   sred->subcommtype    = PETSC_SUBCOMM_INTERLACED;
10561e07b27eSBarry Smith   sred->redfactor      = 1;
10571e07b27eSBarry Smith   sred->ignore_dm      = PETSC_FALSE;
10587c5279cbSDave May   sred->ignore_kspcomputeoperators = PETSC_FALSE;
10591e07b27eSBarry Smith   pc->data             = (void*)sred;
10601e07b27eSBarry Smith 
10611e07b27eSBarry Smith   pc->ops->apply           = PCApply_Telescope;
10621e07b27eSBarry Smith   pc->ops->applytranspose  = NULL;
1063f650675bSDave May   pc->ops->applyrichardson = PCApplyRichardson_Telescope;
10641e07b27eSBarry Smith   pc->ops->setup           = PCSetUp_Telescope;
10651e07b27eSBarry Smith   pc->ops->destroy         = PCDestroy_Telescope;
10661e07b27eSBarry Smith   pc->ops->reset           = PCReset_Telescope;
10671e07b27eSBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_Telescope;
10681e07b27eSBarry Smith   pc->ops->view            = PCView_Telescope;
10691e07b27eSBarry Smith 
10701e07b27eSBarry Smith   sred->pctelescope_setup_type              = PCTelescopeSetUp_default;
10711e07b27eSBarry Smith   sred->pctelescope_matcreate_type          = PCTelescopeMatCreate_default;
10721e07b27eSBarry Smith   sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_default;
10731e07b27eSBarry Smith   sred->pctelescope_reset_type              = NULL;
10741e07b27eSBarry Smith 
10751e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetKSP_C",PCTelescopeGetKSP_Telescope);CHKERRQ(ierr);
107648a10b22SPatrick Sanan   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetSubcommType_C",PCTelescopeGetSubcommType_Telescope);CHKERRQ(ierr);
107748a10b22SPatrick Sanan   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetSubcommType_C",PCTelescopeSetSubcommType_Telescope);CHKERRQ(ierr);
10781e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetReductionFactor_C",PCTelescopeGetReductionFactor_Telescope);CHKERRQ(ierr);
10791e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetReductionFactor_C",PCTelescopeSetReductionFactor_Telescope);CHKERRQ(ierr);
10801e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetIgnoreDM_C",PCTelescopeGetIgnoreDM_Telescope);CHKERRQ(ierr);
10811e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetIgnoreDM_C",PCTelescopeSetIgnoreDM_Telescope);CHKERRQ(ierr);
10820ae7c45bSDave May   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetIgnoreKSPComputeOperators_C",PCTelescopeGetIgnoreKSPComputeOperators_Telescope);CHKERRQ(ierr);
10830ae7c45bSDave May   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetIgnoreKSPComputeOperators_C",PCTelescopeSetIgnoreKSPComputeOperators_Telescope);CHKERRQ(ierr);
10841e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetDM_C",PCTelescopeGetDM_Telescope);CHKERRQ(ierr);
10851e07b27eSBarry Smith   PetscFunctionReturn(0);
10861e07b27eSBarry Smith }
1087