xref: /petsc/src/ksp/pc/impls/telescope/telescope.c (revision 2c71b3e237ead271e4f3aa1505f92bf476e3413d)
18d9f7141SDave May #include <petsc/private/petscimpl.h>
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 
8bf00f589SPatrick Sanan static PetscBool  cited = PETSC_FALSE;
9bf00f589SPatrick Sanan static const char citation[] =
10bf00f589SPatrick Sanan "@inproceedings{MaySananRuppKnepleySmith2016,\n"
11bf00f589SPatrick Sanan "  title     = {Extreme-Scale Multigrid Components within PETSc},\n"
12bf00f589SPatrick Sanan "  author    = {Dave A. May and Patrick Sanan and Karl Rupp and Matthew G. Knepley and Barry F. Smith},\n"
13bf00f589SPatrick Sanan "  booktitle = {Proceedings of the Platform for Advanced Scientific Computing Conference},\n"
14bf00f589SPatrick Sanan "  series    = {PASC '16},\n"
15bf00f589SPatrick Sanan "  isbn      = {978-1-4503-4126-4},\n"
16bf00f589SPatrick Sanan "  location  = {Lausanne, Switzerland},\n"
17bf00f589SPatrick Sanan "  pages     = {5:1--5:12},\n"
18bf00f589SPatrick Sanan "  articleno = {5},\n"
19bf00f589SPatrick Sanan "  numpages  = {12},\n"
20a8d69d7bSBarry Smith "  url       = {https://doi.acm.org/10.1145/2929908.2929913},\n"
21bf00f589SPatrick Sanan "  doi       = {10.1145/2929908.2929913},\n"
22bf00f589SPatrick Sanan "  acmid     = {2929913},\n"
23bf00f589SPatrick Sanan "  publisher = {ACM},\n"
24bf00f589SPatrick Sanan "  address   = {New York, NY, USA},\n"
25bf00f589SPatrick Sanan "  keywords  = {GPU, HPC, agglomeration, coarse-level solver, multigrid, parallel computing, preconditioning},\n"
26bf00f589SPatrick Sanan "  year      = {2016}\n"
27bf00f589SPatrick Sanan "}\n";
28bf00f589SPatrick Sanan 
291e07b27eSBarry Smith /*
30c5083d92SDave May  default setup mode
311e07b27eSBarry Smith 
32c5083d92SDave May  [1a] scatter to (FORWARD)
331e07b27eSBarry Smith  x(comm) -> xtmp(comm)
34c5083d92SDave May  [1b] local copy (to) ranks with color = 0
351e07b27eSBarry Smith  xred(subcomm) <- xtmp
361e07b27eSBarry Smith 
37c5083d92SDave May  [2] solve on sub KSP to obtain yred(subcomm)
38c5083d92SDave May 
39c5083d92SDave May  [3a] local copy (from) ranks with color = 0
401e07b27eSBarry Smith  yred(subcomm) --> xtmp
41c5083d92SDave May  [2b] scatter from (REVERSE)
421e07b27eSBarry Smith  xtmp(comm) -> y(comm)
431e07b27eSBarry Smith */
441e07b27eSBarry Smith 
458d9f7141SDave May /*
46d083f849SBarry Smith   Collective[comm_f]
478d9f7141SDave May   Notes
488d9f7141SDave May    * Using comm_f = MPI_COMM_NULL will result in an error
498d9f7141SDave May    * Using comm_c = MPI_COMM_NULL is valid. If all instances of comm_c are NULL the subcomm is not valid.
508d9f7141SDave May    * If any non NULL comm_c communicator cannot map any of its ranks to comm_f, the subcomm is not valid.
518d9f7141SDave May */
528d9f7141SDave May PetscErrorCode PCTelescopeTestValidSubcomm(MPI_Comm comm_f,MPI_Comm comm_c,PetscBool *isvalid)
538d9f7141SDave May {
5457f12427SDave May   PetscInt       valid = 1;
558d9f7141SDave May   MPI_Group      group_f,group_c;
568d9f7141SDave May   PetscErrorCode ierr;
578d9f7141SDave May   PetscMPIInt    count,k,size_f = 0,size_c = 0,size_c_sum = 0;
585bd1e576SStefano Zampini   PetscMPIInt    *ranks_f,*ranks_c;
598d9f7141SDave May 
6057f12427SDave May   PetscFunctionBegin;
61*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(comm_f == MPI_COMM_NULL,PETSC_COMM_SELF,PETSC_ERR_SUP,"comm_f cannot be MPI_COMM_NULL");
628d9f7141SDave May 
63ffc4695bSBarry Smith   ierr = MPI_Comm_group(comm_f,&group_f);CHKERRMPI(ierr);
648d9f7141SDave May   if (comm_c != MPI_COMM_NULL) {
65ffc4695bSBarry Smith     ierr = MPI_Comm_group(comm_c,&group_c);CHKERRMPI(ierr);
668d9f7141SDave May   }
678d9f7141SDave May 
68ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm_f,&size_f);CHKERRMPI(ierr);
698d9f7141SDave May   if (comm_c != MPI_COMM_NULL) {
70ffc4695bSBarry Smith     ierr = MPI_Comm_size(comm_c,&size_c);CHKERRMPI(ierr);
718d9f7141SDave May   }
728d9f7141SDave May 
738d9f7141SDave May   /* check not all comm_c's are NULL */
748d9f7141SDave May   size_c_sum = size_c;
75ffc4695bSBarry Smith   ierr = MPI_Allreduce(MPI_IN_PLACE,&size_c_sum,1,MPI_INT,MPI_SUM,comm_f);CHKERRMPI(ierr);
765bd1e576SStefano Zampini   if (size_c_sum == 0) valid = 0;
778d9f7141SDave May 
788d9f7141SDave May   /* check we can map at least 1 rank in comm_c to comm_f */
798d9f7141SDave May   ierr = PetscMalloc1(size_f,&ranks_f);CHKERRQ(ierr);
808d9f7141SDave May   ierr = PetscMalloc1(size_c,&ranks_c);CHKERRQ(ierr);
815bd1e576SStefano Zampini   for (k=0; k<size_f; k++) ranks_f[k] = MPI_UNDEFINED;
825bd1e576SStefano Zampini   for (k=0; k<size_c; k++) ranks_c[k] = k;
838d9f7141SDave May 
8457f12427SDave May   /*
8557f12427SDave May    MPI_Group_translate_ranks() returns a non-zero exit code if any rank cannot be translated.
8657f12427SDave May    I do not want the code to terminate immediately if this occurs, rather I want to throw
8757f12427SDave May    the error later (during PCSetUp_Telescope()) via SETERRQ() with a message indicating
8857f12427SDave May    that comm_c is not a valid sub-communicator.
8957f12427SDave May    Hence I purposefully do not call CHKERRQ() after MPI_Group_translate_ranks().
9057f12427SDave May   */
918d9f7141SDave May   count = 0;
928d9f7141SDave May   if (comm_c != MPI_COMM_NULL) {
9366b79024SDave May     (void)MPI_Group_translate_ranks(group_c,size_c,ranks_c,group_f,ranks_f);
948d9f7141SDave May     for (k=0; k<size_f; k++) {
958d9f7141SDave May       if (ranks_f[k] == MPI_UNDEFINED) {
968d9f7141SDave May         count++;
978d9f7141SDave May       }
988d9f7141SDave May     }
998d9f7141SDave May   }
1005bd1e576SStefano Zampini   if (count == size_f) valid = 0;
1018d9f7141SDave May 
102ffc4695bSBarry Smith   ierr = MPI_Allreduce(MPI_IN_PLACE,&valid,1,MPIU_INT,MPI_MIN,comm_f);CHKERRMPI(ierr);
1035bd1e576SStefano Zampini   if (valid == 1) *isvalid = PETSC_TRUE;
1045bd1e576SStefano Zampini   else *isvalid = PETSC_FALSE;
1058d9f7141SDave May 
1068d9f7141SDave May   ierr = PetscFree(ranks_f);CHKERRQ(ierr);
1078d9f7141SDave May   ierr = PetscFree(ranks_c);CHKERRQ(ierr);
108ffc4695bSBarry Smith   ierr = MPI_Group_free(&group_f);CHKERRMPI(ierr);
1098d9f7141SDave May   if (comm_c != MPI_COMM_NULL) {
110ffc4695bSBarry Smith     ierr = MPI_Group_free(&group_c);CHKERRMPI(ierr);
1118d9f7141SDave May   }
1128d9f7141SDave May   PetscFunctionReturn(0);
1138d9f7141SDave May }
1148d9f7141SDave May 
1151e07b27eSBarry Smith DM private_PCTelescopeGetSubDM(PC_Telescope sred)
1161e07b27eSBarry Smith {
117c6a0d831SBarry Smith   DM subdm = NULL;
1181e07b27eSBarry Smith 
11957f12427SDave May   if (!PCTelescope_isActiveRank(sred)) { subdm = NULL; }
1201e07b27eSBarry Smith   else {
1211e07b27eSBarry Smith     switch (sred->sr_type) {
1221e07b27eSBarry Smith     case TELESCOPE_DEFAULT: subdm = NULL;
1231e07b27eSBarry Smith       break;
1241e07b27eSBarry Smith     case TELESCOPE_DMDA:    subdm = ((PC_Telescope_DMDACtx*)sred->dm_ctx)->dmrepart;
1251e07b27eSBarry Smith       break;
1261e07b27eSBarry Smith     case TELESCOPE_DMPLEX:  subdm = NULL;
1271e07b27eSBarry Smith       break;
1288d9f7141SDave May     case TELESCOPE_COARSEDM: if (sred->ksp) { KSPGetDM(sred->ksp,&subdm); }
1298d9f7141SDave May       break;
1301e07b27eSBarry Smith     }
1311e07b27eSBarry Smith   }
1321e07b27eSBarry Smith   return(subdm);
1331e07b27eSBarry Smith }
1341e07b27eSBarry Smith 
1351e07b27eSBarry Smith PetscErrorCode PCTelescopeSetUp_default(PC pc,PC_Telescope sred)
1361e07b27eSBarry Smith {
1371e07b27eSBarry Smith   PetscErrorCode ierr;
1381e07b27eSBarry Smith   PetscInt       m,M,bs,st,ed;
1391e07b27eSBarry Smith   Vec            x,xred,yred,xtmp;
1401e07b27eSBarry Smith   Mat            B;
1411e07b27eSBarry Smith   MPI_Comm       comm,subcomm;
1421e07b27eSBarry Smith   VecScatter     scatter;
1431e07b27eSBarry Smith   IS             isin;
14454cd43dcSJunchao Zhang   VecType        vectype;
1451e07b27eSBarry Smith 
1461e07b27eSBarry Smith   PetscFunctionBegin;
1471e07b27eSBarry Smith   ierr = PetscInfo(pc,"PCTelescope: setup (default)\n");CHKERRQ(ierr);
1481e07b27eSBarry Smith   comm = PetscSubcommParent(sred->psubcomm);
1491e07b27eSBarry Smith   subcomm = PetscSubcommChild(sred->psubcomm);
1501e07b27eSBarry Smith 
1511e07b27eSBarry Smith   ierr = PCGetOperators(pc,NULL,&B);CHKERRQ(ierr);
1521e07b27eSBarry Smith   ierr = MatGetSize(B,&M,NULL);CHKERRQ(ierr);
1531e07b27eSBarry Smith   ierr = MatGetBlockSize(B,&bs);CHKERRQ(ierr);
1541e07b27eSBarry Smith   ierr = MatCreateVecs(B,&x,NULL);CHKERRQ(ierr);
15554cd43dcSJunchao Zhang   ierr = MatGetVecType(B,&vectype);CHKERRQ(ierr);
1561e07b27eSBarry Smith 
1571e07b27eSBarry Smith   xred = NULL;
1583ac26c5eSBarry Smith   m    = 0;
15957f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
1601e07b27eSBarry Smith     ierr = VecCreate(subcomm,&xred);CHKERRQ(ierr);
1611e07b27eSBarry Smith     ierr = VecSetSizes(xred,PETSC_DECIDE,M);CHKERRQ(ierr);
1621e07b27eSBarry Smith     ierr = VecSetBlockSize(xred,bs);CHKERRQ(ierr);
16354cd43dcSJunchao Zhang     ierr = VecSetType(xred,vectype);CHKERRQ(ierr); /* Use the preconditioner matrix's vectype by default */
1641e07b27eSBarry Smith     ierr = VecSetFromOptions(xred);CHKERRQ(ierr);
165ca43db0aSBarry Smith     ierr = VecGetLocalSize(xred,&m);CHKERRQ(ierr);
1661e07b27eSBarry Smith   }
1671e07b27eSBarry Smith 
1681e07b27eSBarry Smith   yred = NULL;
16957f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
1701e07b27eSBarry Smith     ierr = VecDuplicate(xred,&yred);CHKERRQ(ierr);
1711e07b27eSBarry Smith   }
1721e07b27eSBarry Smith 
1731e07b27eSBarry Smith   ierr = VecCreate(comm,&xtmp);CHKERRQ(ierr);
1741e07b27eSBarry Smith   ierr = VecSetSizes(xtmp,m,PETSC_DECIDE);CHKERRQ(ierr);
1751e07b27eSBarry Smith   ierr = VecSetBlockSize(xtmp,bs);CHKERRQ(ierr);
17654cd43dcSJunchao Zhang   ierr = VecSetType(xtmp,vectype);CHKERRQ(ierr);
1771e07b27eSBarry Smith 
17857f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
1791e07b27eSBarry Smith     ierr = VecGetOwnershipRange(xred,&st,&ed);CHKERRQ(ierr);
1801e07b27eSBarry Smith     ierr = ISCreateStride(comm,(ed-st),st,1,&isin);CHKERRQ(ierr);
1811e07b27eSBarry Smith   } else {
1821e07b27eSBarry Smith     ierr = VecGetOwnershipRange(x,&st,&ed);CHKERRQ(ierr);
1833ac26c5eSBarry Smith     ierr = ISCreateStride(comm,0,st,1,&isin);CHKERRQ(ierr);
1841e07b27eSBarry Smith   }
1851e07b27eSBarry Smith   ierr = ISSetBlockSize(isin,bs);CHKERRQ(ierr);
1861e07b27eSBarry Smith 
1879448b7f1SJunchao Zhang   ierr = VecScatterCreate(x,isin,xtmp,NULL,&scatter);CHKERRQ(ierr);
1881e07b27eSBarry Smith 
1891e07b27eSBarry Smith   sred->isin    = isin;
1901e07b27eSBarry Smith   sred->scatter = scatter;
1911e07b27eSBarry Smith   sred->xred    = xred;
1921e07b27eSBarry Smith   sred->yred    = yred;
1931e07b27eSBarry Smith   sred->xtmp    = xtmp;
1941e07b27eSBarry Smith   ierr = VecDestroy(&x);CHKERRQ(ierr);
1951e07b27eSBarry Smith   PetscFunctionReturn(0);
1961e07b27eSBarry Smith }
1971e07b27eSBarry Smith 
1981e07b27eSBarry Smith PetscErrorCode PCTelescopeMatCreate_default(PC pc,PC_Telescope sred,MatReuse reuse,Mat *A)
1991e07b27eSBarry Smith {
2001e07b27eSBarry Smith   PetscErrorCode ierr;
2011e07b27eSBarry Smith   MPI_Comm       comm,subcomm;
2021e07b27eSBarry Smith   Mat            Bred,B;
2035624f943SPierre Jolivet   PetscInt       nr,nc,bs;
2041e07b27eSBarry Smith   IS             isrow,iscol;
2051e07b27eSBarry Smith   Mat            Blocal,*_Blocal;
2061e07b27eSBarry Smith 
2071e07b27eSBarry Smith   PetscFunctionBegin;
2081e07b27eSBarry Smith   ierr = PetscInfo(pc,"PCTelescope: updating the redundant preconditioned operator (default)\n");CHKERRQ(ierr);
2091e07b27eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
2101e07b27eSBarry Smith   subcomm = PetscSubcommChild(sred->psubcomm);
2111e07b27eSBarry Smith   ierr = PCGetOperators(pc,NULL,&B);CHKERRQ(ierr);
2121e07b27eSBarry Smith   ierr = MatGetSize(B,&nr,&nc);CHKERRQ(ierr);
2131e07b27eSBarry Smith   isrow = sred->isin;
214ee5b8cbaSprj-   ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&iscol);CHKERRQ(ierr);
215ee5b8cbaSprj-   ierr = ISSetIdentity(iscol);CHKERRQ(ierr);
2165624f943SPierre Jolivet   ierr = MatGetBlockSizes(B,NULL,&bs);CHKERRQ(ierr);
2175624f943SPierre Jolivet   ierr = ISSetBlockSize(iscol,bs);CHKERRQ(ierr);
218ee5b8cbaSprj-   ierr = MatSetOption(B,MAT_SUBMAT_SINGLEIS,PETSC_TRUE);CHKERRQ(ierr);
2197dae84e0SHong Zhang   ierr = MatCreateSubMatrices(B,1,&isrow,&iscol,MAT_INITIAL_MATRIX,&_Blocal);CHKERRQ(ierr);
2201e07b27eSBarry Smith   Blocal = *_Blocal;
2211e07b27eSBarry Smith   ierr = PetscFree(_Blocal);CHKERRQ(ierr);
2221e07b27eSBarry Smith   Bred = NULL;
22357f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
2241e07b27eSBarry Smith     PetscInt mm;
2251e07b27eSBarry Smith 
2261e07b27eSBarry Smith     if (reuse != MAT_INITIAL_MATRIX) { Bred = *A; }
2271e07b27eSBarry Smith 
2281e07b27eSBarry Smith     ierr = MatGetSize(Blocal,&mm,NULL);CHKERRQ(ierr);
2291e07b27eSBarry Smith     ierr = MatCreateMPIMatConcatenateSeqMat(subcomm,Blocal,mm,reuse,&Bred);CHKERRQ(ierr);
2301e07b27eSBarry Smith   }
2311e07b27eSBarry Smith   *A = Bred;
2321e07b27eSBarry Smith   ierr = ISDestroy(&iscol);CHKERRQ(ierr);
2331e07b27eSBarry Smith   ierr = MatDestroy(&Blocal);CHKERRQ(ierr);
2341e07b27eSBarry Smith   PetscFunctionReturn(0);
2351e07b27eSBarry Smith }
2361e07b27eSBarry Smith 
237392968a1SPatrick Sanan static PetscErrorCode PCTelescopeSubNullSpaceCreate_Telescope(PC pc,PC_Telescope sred,MatNullSpace nullspace,MatNullSpace *sub_nullspace)
2381e07b27eSBarry Smith {
2391e07b27eSBarry Smith   PetscErrorCode ierr;
2401e07b27eSBarry Smith   PetscBool      has_const;
2411e07b27eSBarry Smith   const Vec      *vecs;
242c41e779fSDave May   Vec            *sub_vecs = NULL;
243392968a1SPatrick Sanan   PetscInt       i,k,n = 0;
2441e07b27eSBarry Smith   MPI_Comm       subcomm;
2451e07b27eSBarry Smith 
2461e07b27eSBarry Smith   PetscFunctionBegin;
2471e07b27eSBarry Smith   subcomm = PetscSubcommChild(sred->psubcomm);
2481e07b27eSBarry Smith   ierr = MatNullSpaceGetVecs(nullspace,&has_const,&n,&vecs);CHKERRQ(ierr);
2491e07b27eSBarry Smith 
25057f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
251e3acf2f7SBarry Smith     if (n) {
252e3acf2f7SBarry Smith       ierr = VecDuplicateVecs(sred->xred,n,&sub_vecs);CHKERRQ(ierr);
2531e07b27eSBarry Smith     }
2541e07b27eSBarry Smith   }
2551e07b27eSBarry Smith 
2561e07b27eSBarry Smith   /* copy entries */
2571e07b27eSBarry Smith   for (k=0; k<n; k++) {
2581e07b27eSBarry Smith     const PetscScalar *x_array;
2591e07b27eSBarry Smith     PetscScalar       *LA_sub_vec;
26013c30530SDave May     PetscInt          st,ed;
2611e07b27eSBarry Smith 
2621e07b27eSBarry Smith     /* pull in vector x->xtmp */
2631e07b27eSBarry Smith     ierr = VecScatterBegin(sred->scatter,vecs[k],sred->xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2641e07b27eSBarry Smith     ierr = VecScatterEnd(sred->scatter,vecs[k],sred->xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
26547856c66SBarry Smith     if (sub_vecs) {
266a04a6428SPatrick Sanan       /* copy vector entries into xred */
2671e07b27eSBarry Smith       ierr = VecGetArrayRead(sred->xtmp,&x_array);CHKERRQ(ierr);
268ea2b237eSDave May       if (sub_vecs[k]) {
2691e07b27eSBarry Smith         ierr = VecGetOwnershipRange(sub_vecs[k],&st,&ed);CHKERRQ(ierr);
2701e07b27eSBarry Smith         ierr = VecGetArray(sub_vecs[k],&LA_sub_vec);CHKERRQ(ierr);
2711e07b27eSBarry Smith         for (i=0; i<ed-st; i++) {
2721e07b27eSBarry Smith           LA_sub_vec[i] = x_array[i];
2731e07b27eSBarry Smith         }
2741e07b27eSBarry Smith         ierr = VecRestoreArray(sub_vecs[k],&LA_sub_vec);CHKERRQ(ierr);
2751e07b27eSBarry Smith       }
2761e07b27eSBarry Smith       ierr = VecRestoreArrayRead(sred->xtmp,&x_array);CHKERRQ(ierr);
2771e07b27eSBarry Smith     }
27847856c66SBarry Smith   }
2791e07b27eSBarry Smith 
28057f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
281d8b9d5b7SPatrick Sanan     /* create new (near) nullspace for redundant object */
282392968a1SPatrick Sanan     ierr = MatNullSpaceCreate(subcomm,has_const,n,sub_vecs,sub_nullspace);CHKERRQ(ierr);
283392968a1SPatrick Sanan     ierr = VecDestroyVecs(n,&sub_vecs);CHKERRQ(ierr);
284*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(nullspace->remove,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Propagation of custom remove callbacks not supported when propagating (near) nullspaces with PCTelescope");
285*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(nullspace->rmctx,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Propagation of custom remove callback context not supported when propagating (near) nullspaces with PCTelescope");
286d8b9d5b7SPatrick Sanan   }
287392968a1SPatrick Sanan   PetscFunctionReturn(0);
288392968a1SPatrick Sanan }
289392968a1SPatrick Sanan 
290392968a1SPatrick Sanan static PetscErrorCode PCTelescopeMatNullSpaceCreate_default(PC pc,PC_Telescope sred,Mat sub_mat)
291392968a1SPatrick Sanan {
292392968a1SPatrick Sanan   PetscErrorCode ierr;
293392968a1SPatrick Sanan   Mat            B;
294392968a1SPatrick Sanan 
295392968a1SPatrick Sanan   PetscFunctionBegin;
296392968a1SPatrick Sanan   ierr = PCGetOperators(pc,NULL,&B);CHKERRQ(ierr);
297392968a1SPatrick Sanan   /* Propagate the nullspace if it exists */
298392968a1SPatrick Sanan   {
299392968a1SPatrick Sanan     MatNullSpace nullspace,sub_nullspace;
300392968a1SPatrick Sanan     ierr = MatGetNullSpace(B,&nullspace);CHKERRQ(ierr);
301392968a1SPatrick Sanan     if (nullspace) {
302392968a1SPatrick Sanan       ierr = PetscInfo(pc,"PCTelescope: generating nullspace (default)\n");CHKERRQ(ierr);
303392968a1SPatrick Sanan       ierr = PCTelescopeSubNullSpaceCreate_Telescope(pc,sred,nullspace,&sub_nullspace);CHKERRQ(ierr);
30457f12427SDave May       if (PCTelescope_isActiveRank(sred)) {
305392968a1SPatrick Sanan         ierr = MatSetNullSpace(sub_mat,sub_nullspace);CHKERRQ(ierr);
30641ff1ee9SPatrick Sanan         ierr = MatNullSpaceDestroy(&sub_nullspace);CHKERRQ(ierr);
3071e07b27eSBarry Smith       }
308392968a1SPatrick Sanan     }
309392968a1SPatrick Sanan   }
310392968a1SPatrick Sanan   /* Propagate the near nullspace if it exists */
311392968a1SPatrick Sanan   {
312392968a1SPatrick Sanan     MatNullSpace nearnullspace,sub_nearnullspace;
313392968a1SPatrick Sanan     ierr = MatGetNearNullSpace(B,&nearnullspace);CHKERRQ(ierr);
314392968a1SPatrick Sanan     if (nearnullspace) {
315392968a1SPatrick Sanan       ierr = PetscInfo(pc,"PCTelescope: generating near nullspace (default)\n");CHKERRQ(ierr);
316392968a1SPatrick Sanan       ierr = PCTelescopeSubNullSpaceCreate_Telescope(pc,sred,nearnullspace,&sub_nearnullspace);CHKERRQ(ierr);
31757f12427SDave May       if (PCTelescope_isActiveRank(sred)) {
318392968a1SPatrick Sanan         ierr = MatSetNearNullSpace(sub_mat,sub_nearnullspace);CHKERRQ(ierr);
319392968a1SPatrick Sanan         ierr = MatNullSpaceDestroy(&sub_nearnullspace);CHKERRQ(ierr);
320392968a1SPatrick Sanan       }
321392968a1SPatrick Sanan     }
322392968a1SPatrick Sanan   }
3231e07b27eSBarry Smith   PetscFunctionReturn(0);
3241e07b27eSBarry Smith }
3251e07b27eSBarry Smith 
3261e07b27eSBarry Smith static PetscErrorCode PCView_Telescope(PC pc,PetscViewer viewer)
3271e07b27eSBarry Smith {
3281e07b27eSBarry Smith   PC_Telescope   sred = (PC_Telescope)pc->data;
3291e07b27eSBarry Smith   PetscErrorCode ierr;
3301e07b27eSBarry Smith   PetscBool      iascii,isstring;
3311e07b27eSBarry Smith   PetscViewer    subviewer;
3321e07b27eSBarry Smith 
3331e07b27eSBarry Smith   PetscFunctionBegin;
3341e07b27eSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
3351e07b27eSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr);
3361e07b27eSBarry Smith   if (iascii) {
3378d9f7141SDave May     {
3381e07b27eSBarry Smith       MPI_Comm    comm,subcomm;
3391e07b27eSBarry Smith       PetscMPIInt comm_size,subcomm_size;
3408d9f7141SDave May       DM          dm = NULL,subdm = NULL;
3411e07b27eSBarry Smith 
3421e07b27eSBarry Smith       ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
3431e07b27eSBarry Smith       subdm = private_PCTelescopeGetSubDM(sred);
3448d9f7141SDave May 
3458d9f7141SDave May       if (sred->psubcomm) {
3461e07b27eSBarry Smith         comm = PetscSubcommParent(sred->psubcomm);
3471e07b27eSBarry Smith         subcomm = PetscSubcommChild(sred->psubcomm);
348ffc4695bSBarry Smith         ierr = MPI_Comm_size(comm,&comm_size);CHKERRMPI(ierr);
349ffc4695bSBarry Smith         ierr = MPI_Comm_size(subcomm,&subcomm_size);CHKERRMPI(ierr);
3501e07b27eSBarry Smith 
3518d9f7141SDave May         ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
3528d9f7141SDave May         ierr = PetscViewerASCIIPrintf(viewer,"petsc subcomm: parent comm size reduction factor = %D\n",sred->redfactor);CHKERRQ(ierr);
3538d9f7141SDave May         ierr = PetscViewerASCIIPrintf(viewer,"petsc subcomm: parent_size = %d , subcomm_size = %d\n",(int)comm_size,(int)subcomm_size);CHKERRQ(ierr);
35448a10b22SPatrick Sanan         switch (sred->subcommtype) {
35548a10b22SPatrick Sanan         case PETSC_SUBCOMM_INTERLACED :
3568d9f7141SDave May           ierr = PetscViewerASCIIPrintf(viewer,"petsc subcomm: type = interlaced\n",sred->subcommtype);CHKERRQ(ierr);
35748a10b22SPatrick Sanan           break;
35848a10b22SPatrick Sanan         case PETSC_SUBCOMM_CONTIGUOUS :
3598d9f7141SDave May           ierr = PetscViewerASCIIPrintf(viewer,"petsc subcomm type = contiguous\n",sred->subcommtype);CHKERRQ(ierr);
36048a10b22SPatrick Sanan           break;
36148a10b22SPatrick Sanan         default :
36248a10b22SPatrick Sanan           SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"General subcomm type not supported by PCTelescope");
36348a10b22SPatrick Sanan         }
3648d9f7141SDave May         ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
3658d9f7141SDave May       } else {
3668d9f7141SDave May         ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
3678d9f7141SDave May         subcomm = sred->subcomm;
36857f12427SDave May         if (!PCTelescope_isActiveRank(sred)) {
3698d9f7141SDave May           subcomm = PETSC_COMM_SELF;
3708d9f7141SDave May         }
3718d9f7141SDave May 
3728d9f7141SDave May         ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
3738d9f7141SDave May         ierr = PetscViewerASCIIPrintf(viewer,"subcomm: using user provided sub-communicator\n");CHKERRQ(ierr);
3748d9f7141SDave May         ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
3758d9f7141SDave May       }
3768d9f7141SDave May 
3771e07b27eSBarry Smith       ierr = PetscViewerGetSubViewer(viewer,subcomm,&subviewer);CHKERRQ(ierr);
37857f12427SDave May       if (PCTelescope_isActiveRank(sred)) {
3791e07b27eSBarry Smith         ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr);
3801e07b27eSBarry Smith 
3811e07b27eSBarry Smith         if (dm && sred->ignore_dm) {
382efd4aadfSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"ignoring DM\n");CHKERRQ(ierr);
3831e07b27eSBarry Smith         }
3847c5279cbSDave May         if (sred->ignore_kspcomputeoperators) {
385efd4aadfSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"ignoring KSPComputeOperators\n");CHKERRQ(ierr);
3867c5279cbSDave May         }
3871e07b27eSBarry Smith         switch (sred->sr_type) {
3881e07b27eSBarry Smith         case TELESCOPE_DEFAULT:
3898d9f7141SDave May           ierr = PetscViewerASCIIPrintf(subviewer,"setup type: default\n");CHKERRQ(ierr);
3901e07b27eSBarry Smith           break;
3911e07b27eSBarry Smith         case TELESCOPE_DMDA:
3928d9f7141SDave May           ierr = PetscViewerASCIIPrintf(subviewer,"setup type: DMDA auto-repartitioning\n");CHKERRQ(ierr);
3938ef9ca65SPatrick Sanan           ierr = DMView_DA_Short(subdm,subviewer);CHKERRQ(ierr);
3941e07b27eSBarry Smith           break;
3951e07b27eSBarry Smith         case TELESCOPE_DMPLEX:
3968d9f7141SDave May           ierr = PetscViewerASCIIPrintf(subviewer,"setup type: DMPLEX auto-repartitioning\n");CHKERRQ(ierr);
3971e07b27eSBarry Smith           break;
3988d9f7141SDave May         case TELESCOPE_COARSEDM:
3998d9f7141SDave May           ierr = PetscViewerASCIIPrintf(subviewer,"setup type: coarse DM\n");CHKERRQ(ierr);
4008d9f7141SDave May           break;
4018d9f7141SDave May         }
4028d9f7141SDave May 
4038d9f7141SDave May         if (dm) {
4048d9f7141SDave May           PetscObject obj = (PetscObject)dm;
4058d9f7141SDave May           ierr = PetscViewerASCIIPrintf(subviewer,"Parent DM object:");CHKERRQ(ierr);
4068d9f7141SDave May           PetscViewerASCIIUseTabs(subviewer,PETSC_FALSE);
4078d9f7141SDave May           if (obj->type_name) { PetscViewerASCIIPrintf(subviewer," type = %s;",obj->type_name); }
4088d9f7141SDave May           if (obj->name) { PetscViewerASCIIPrintf(subviewer," name = %s;",obj->name); }
4098d9f7141SDave May           if (obj->prefix) { PetscViewerASCIIPrintf(subviewer," prefix = %s",obj->prefix); }
4108d9f7141SDave May           ierr = PetscViewerASCIIPrintf(subviewer,"\n");CHKERRQ(ierr);
4118d9f7141SDave May           PetscViewerASCIIUseTabs(subviewer,PETSC_TRUE);
4128d9f7141SDave May         } else {
4138d9f7141SDave May           ierr = PetscViewerASCIIPrintf(subviewer,"Parent DM object: NULL\n");CHKERRQ(ierr);
4148d9f7141SDave May         }
4158d9f7141SDave May         if (subdm) {
4168d9f7141SDave May           PetscObject obj = (PetscObject)subdm;
4178d9f7141SDave May           ierr = PetscViewerASCIIPrintf(subviewer,"Sub DM object:");CHKERRQ(ierr);
4188d9f7141SDave May           PetscViewerASCIIUseTabs(subviewer,PETSC_FALSE);
4198d9f7141SDave May           if (obj->type_name) { PetscViewerASCIIPrintf(subviewer," type = %s;",obj->type_name); }
4208d9f7141SDave May           if (obj->name) { PetscViewerASCIIPrintf(subviewer," name = %s;",obj->name); }
4218d9f7141SDave May           if (obj->prefix) { PetscViewerASCIIPrintf(subviewer," prefix = %s",obj->prefix); }
4228d9f7141SDave May           ierr = PetscViewerASCIIPrintf(subviewer,"\n");CHKERRQ(ierr);
4238d9f7141SDave May           PetscViewerASCIIUseTabs(subviewer,PETSC_TRUE);
4248d9f7141SDave May         } else {
4258d9f7141SDave May           ierr = PetscViewerASCIIPrintf(subviewer,"Sub DM object: NULL\n");CHKERRQ(ierr);
4261e07b27eSBarry Smith         }
4271e07b27eSBarry Smith 
4281e07b27eSBarry Smith         ierr = KSPView(sred->ksp,subviewer);CHKERRQ(ierr);
4291e07b27eSBarry Smith         ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr);
4301e07b27eSBarry Smith       }
4311e07b27eSBarry Smith       ierr = PetscViewerRestoreSubViewer(viewer,subcomm,&subviewer);CHKERRQ(ierr);
4321e07b27eSBarry Smith     }
4331e07b27eSBarry Smith   }
4341e07b27eSBarry Smith   PetscFunctionReturn(0);
4351e07b27eSBarry Smith }
4361e07b27eSBarry Smith 
4371e07b27eSBarry Smith static PetscErrorCode PCSetUp_Telescope(PC pc)
4381e07b27eSBarry Smith {
4391e07b27eSBarry Smith   PC_Telescope    sred = (PC_Telescope)pc->data;
4401e07b27eSBarry Smith   PetscErrorCode  ierr;
441bd49479cSSatish Balay   MPI_Comm        comm,subcomm=0;
4421e07b27eSBarry Smith   PCTelescopeType sr_type;
4431e07b27eSBarry Smith 
4441e07b27eSBarry Smith   PetscFunctionBegin;
4451e07b27eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
4461e07b27eSBarry Smith 
4471e07b27eSBarry Smith   /* Determine type of setup/update */
4481e07b27eSBarry Smith   if (!pc->setupcalled) {
4491e07b27eSBarry Smith     PetscBool has_dm,same;
4501e07b27eSBarry Smith     DM        dm;
4511e07b27eSBarry Smith 
4521e07b27eSBarry Smith     sr_type = TELESCOPE_DEFAULT;
4531e07b27eSBarry Smith     has_dm = PETSC_FALSE;
4541e07b27eSBarry Smith     ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
4551e07b27eSBarry Smith     if (dm) { has_dm = PETSC_TRUE; }
4561e07b27eSBarry Smith     if (has_dm) {
4571e07b27eSBarry Smith       /* check for dmda */
4581e07b27eSBarry Smith       ierr = PetscObjectTypeCompare((PetscObject)dm,DMDA,&same);CHKERRQ(ierr);
4591e07b27eSBarry Smith       if (same) {
4601e07b27eSBarry Smith         ierr = PetscInfo(pc,"PCTelescope: found DMDA\n");CHKERRQ(ierr);
4611e07b27eSBarry Smith         sr_type = TELESCOPE_DMDA;
4621e07b27eSBarry Smith       }
4631e07b27eSBarry Smith       /* check for dmplex */
4641e07b27eSBarry Smith       ierr = PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&same);CHKERRQ(ierr);
4651e07b27eSBarry Smith       if (same) {
466994fe344SLisandro Dalcin         ierr = PetscInfo(pc,"PCTelescope: found DMPLEX\n");CHKERRQ(ierr);
4671e07b27eSBarry Smith         sr_type = TELESCOPE_DMPLEX;
4681e07b27eSBarry Smith       }
4698d9f7141SDave May 
4708d9f7141SDave May       if (sred->use_coarse_dm) {
4718d9f7141SDave May         ierr = PetscInfo(pc,"PCTelescope: using coarse DM\n");CHKERRQ(ierr);
4728d9f7141SDave May         sr_type = TELESCOPE_COARSEDM;
4731e07b27eSBarry Smith       }
4741e07b27eSBarry Smith 
4751e07b27eSBarry Smith       if (sred->ignore_dm) {
4768d9f7141SDave May         ierr = PetscInfo(pc,"PCTelescope: ignoring DM\n");CHKERRQ(ierr);
4771e07b27eSBarry Smith         sr_type = TELESCOPE_DEFAULT;
4781e07b27eSBarry Smith       }
4798d9f7141SDave May     }
4801e07b27eSBarry Smith     sred->sr_type = sr_type;
4811e07b27eSBarry Smith   } else {
4821e07b27eSBarry Smith     sr_type = sred->sr_type;
4831e07b27eSBarry Smith   }
4841e07b27eSBarry Smith 
485d8b9d5b7SPatrick Sanan   /* set function pointers for repartition setup, matrix creation/update, matrix (near) nullspace, and reset functionality */
4861e07b27eSBarry Smith   switch (sr_type) {
4871e07b27eSBarry Smith   case TELESCOPE_DEFAULT:
4881e07b27eSBarry Smith     sred->pctelescope_setup_type              = PCTelescopeSetUp_default;
4891e07b27eSBarry Smith     sred->pctelescope_matcreate_type          = PCTelescopeMatCreate_default;
4901e07b27eSBarry Smith     sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_default;
4911e07b27eSBarry Smith     sred->pctelescope_reset_type              = NULL;
4921e07b27eSBarry Smith     break;
4931e07b27eSBarry Smith   case TELESCOPE_DMDA:
4941e07b27eSBarry Smith     pc->ops->apply                            = PCApply_Telescope_dmda;
495f650675bSDave May     pc->ops->applyrichardson                  = PCApplyRichardson_Telescope_dmda;
4961e07b27eSBarry Smith     sred->pctelescope_setup_type              = PCTelescopeSetUp_dmda;
4971e07b27eSBarry Smith     sred->pctelescope_matcreate_type          = PCTelescopeMatCreate_dmda;
4981e07b27eSBarry Smith     sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_dmda;
4991e07b27eSBarry Smith     sred->pctelescope_reset_type              = PCReset_Telescope_dmda;
5001e07b27eSBarry Smith     break;
501b458e8f1SJose E. Roman   case TELESCOPE_DMPLEX:
502b458e8f1SJose E. Roman     SETERRQ(comm,PETSC_ERR_SUP,"Support for DMPLEX is currently not available");
5038d9f7141SDave May   case TELESCOPE_COARSEDM:
5048d9f7141SDave May     pc->ops->apply                            = PCApply_Telescope_CoarseDM;
5058d9f7141SDave May     pc->ops->applyrichardson                  = PCApplyRichardson_Telescope_CoarseDM;
5068d9f7141SDave May     sred->pctelescope_setup_type              = PCTelescopeSetUp_CoarseDM;
5078d9f7141SDave May     sred->pctelescope_matcreate_type          = NULL;
5088d9f7141SDave May     sred->pctelescope_matnullspacecreate_type = NULL; /* PCTelescopeMatNullSpaceCreate_CoarseDM; */
5098d9f7141SDave May     sred->pctelescope_reset_type              = PCReset_Telescope_CoarseDM;
5101e07b27eSBarry Smith     break;
511b458e8f1SJose E. Roman   default:
512b458e8f1SJose E. Roman     SETERRQ(comm,PETSC_ERR_SUP,"Support only provided for: repartitioning an operator; repartitioning a DMDA; or using a coarse DM");
5138d9f7141SDave May   }
5148d9f7141SDave May 
5158d9f7141SDave May   /* subcomm definition */
5168d9f7141SDave May   if (!pc->setupcalled) {
5178d9f7141SDave May     if ((sr_type == TELESCOPE_DEFAULT) || (sr_type == TELESCOPE_DMDA)) {
5188d9f7141SDave May       if (!sred->psubcomm) {
5198d9f7141SDave May         ierr = PetscSubcommCreate(comm,&sred->psubcomm);CHKERRQ(ierr);
5208d9f7141SDave May         ierr = PetscSubcommSetNumber(sred->psubcomm,sred->redfactor);CHKERRQ(ierr);
5218d9f7141SDave May         ierr = PetscSubcommSetType(sred->psubcomm,sred->subcommtype);CHKERRQ(ierr);
5228d9f7141SDave May         ierr = PetscLogObjectMemory((PetscObject)pc,sizeof(PetscSubcomm));CHKERRQ(ierr);
5238d9f7141SDave May         sred->subcomm = PetscSubcommChild(sred->psubcomm);
5248d9f7141SDave May       }
5258d9f7141SDave May     } else { /* query PC for DM, check communicators */
5268d9f7141SDave May       DM          dm,dm_coarse_partition = NULL;
5278d9f7141SDave May       MPI_Comm    comm_fine,comm_coarse_partition = MPI_COMM_NULL;
5288d9f7141SDave May       PetscMPIInt csize_fine=0,csize_coarse_partition=0,cs[2],csg[2],cnt=0;
5298d9f7141SDave May       PetscBool   isvalidsubcomm;
5308d9f7141SDave May 
5318d9f7141SDave May       ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
5328d9f7141SDave May       comm_fine = PetscObjectComm((PetscObject)dm);
5338d9f7141SDave May       ierr = DMGetCoarseDM(dm,&dm_coarse_partition);CHKERRQ(ierr);
5348d9f7141SDave May       if (dm_coarse_partition) { cnt = 1; }
535ffc4695bSBarry Smith       ierr = MPI_Allreduce(MPI_IN_PLACE,&cnt,1,MPI_INT,MPI_SUM,comm_fine);CHKERRMPI(ierr);
536*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(cnt == 0,comm_fine,PETSC_ERR_SUP,"Zero instances of a coarse DM were found");
5378d9f7141SDave May 
538ffc4695bSBarry Smith       ierr = MPI_Comm_size(comm_fine,&csize_fine);CHKERRMPI(ierr);
5398d9f7141SDave May       if (dm_coarse_partition) {
5408d9f7141SDave May         comm_coarse_partition = PetscObjectComm((PetscObject)dm_coarse_partition);
541ffc4695bSBarry Smith         ierr = MPI_Comm_size(comm_coarse_partition,&csize_coarse_partition);CHKERRMPI(ierr);
5428d9f7141SDave May       }
5438d9f7141SDave May 
5448d9f7141SDave May       cs[0] = csize_fine;
5458d9f7141SDave May       cs[1] = csize_coarse_partition;
546ffc4695bSBarry Smith       ierr = MPI_Allreduce(cs,csg,2,MPI_INT,MPI_MAX,comm_fine);CHKERRMPI(ierr);
547*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(csg[0] == csg[1],comm_fine,PETSC_ERR_SUP,"Coarse DM uses the same size communicator as the parent DM attached to the PC");
5488d9f7141SDave May 
5498d9f7141SDave May       ierr = PCTelescopeTestValidSubcomm(comm_fine,comm_coarse_partition,&isvalidsubcomm);CHKERRQ(ierr);
550*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(!isvalidsubcomm,comm_fine,PETSC_ERR_SUP,"Coarse DM communicator is not a sub-communicator of parentDM->comm");
5518d9f7141SDave May       sred->subcomm = comm_coarse_partition;
5528d9f7141SDave May     }
5538d9f7141SDave May   }
5548d9f7141SDave May   subcomm = sred->subcomm;
5558d9f7141SDave May 
5568d9f7141SDave May   /* internal KSP */
5578d9f7141SDave May   if (!pc->setupcalled) {
5588d9f7141SDave May     const char *prefix;
5598d9f7141SDave May 
56057f12427SDave May     if (PCTelescope_isActiveRank(sred)) {
5618d9f7141SDave May       ierr = KSPCreate(subcomm,&sred->ksp);CHKERRQ(ierr);
5628d9f7141SDave May       ierr = KSPSetErrorIfNotConverged(sred->ksp,pc->erroriffailure);CHKERRQ(ierr);
5638d9f7141SDave May       ierr = PetscObjectIncrementTabLevel((PetscObject)sred->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
5648d9f7141SDave May       ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)sred->ksp);CHKERRQ(ierr);
5658d9f7141SDave May       ierr = KSPSetType(sred->ksp,KSPPREONLY);CHKERRQ(ierr);
5668d9f7141SDave May       ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
5678d9f7141SDave May       ierr = KSPSetOptionsPrefix(sred->ksp,prefix);CHKERRQ(ierr);
5688d9f7141SDave May       ierr = KSPAppendOptionsPrefix(sred->ksp,"telescope_");CHKERRQ(ierr);
5698d9f7141SDave May     }
5701e07b27eSBarry Smith   }
5711e07b27eSBarry Smith 
5721e07b27eSBarry Smith   /* setup */
573aaa7a805SDave May   if (!pc->setupcalled && sred->pctelescope_setup_type) {
5741e07b27eSBarry Smith     ierr = sred->pctelescope_setup_type(pc,sred);CHKERRQ(ierr);
5751e07b27eSBarry Smith   }
5761e07b27eSBarry Smith   /* update */
5771e07b27eSBarry Smith   if (!pc->setupcalled) {
5781e07b27eSBarry Smith     if (sred->pctelescope_matcreate_type) {
5791e07b27eSBarry Smith       ierr = sred->pctelescope_matcreate_type(pc,sred,MAT_INITIAL_MATRIX,&sred->Bred);CHKERRQ(ierr);
5801e07b27eSBarry Smith     }
5811e07b27eSBarry Smith     if (sred->pctelescope_matnullspacecreate_type) {
582392968a1SPatrick Sanan       ierr = sred->pctelescope_matnullspacecreate_type(pc,sred,sred->Bred);CHKERRQ(ierr);
5831e07b27eSBarry Smith     }
5841e07b27eSBarry Smith   } else {
5851e07b27eSBarry Smith     if (sred->pctelescope_matcreate_type) {
5861e07b27eSBarry Smith       ierr = sred->pctelescope_matcreate_type(pc,sred,MAT_REUSE_MATRIX,&sred->Bred);CHKERRQ(ierr);
5871e07b27eSBarry Smith     }
5881e07b27eSBarry Smith   }
5891e07b27eSBarry Smith 
5901e07b27eSBarry Smith   /* common - no construction */
59157f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
5921e07b27eSBarry Smith     ierr = KSPSetOperators(sred->ksp,sred->Bred,sred->Bred);CHKERRQ(ierr);
5931e07b27eSBarry Smith     if (pc->setfromoptionscalled && !pc->setupcalled) {
5941e07b27eSBarry Smith       ierr = KSPSetFromOptions(sred->ksp);CHKERRQ(ierr);
5951e07b27eSBarry Smith     }
5961e07b27eSBarry Smith   }
5971e07b27eSBarry Smith   PetscFunctionReturn(0);
5981e07b27eSBarry Smith }
5991e07b27eSBarry Smith 
6001e07b27eSBarry Smith static PetscErrorCode PCApply_Telescope(PC pc,Vec x,Vec y)
6011e07b27eSBarry Smith {
6021e07b27eSBarry Smith   PC_Telescope      sred = (PC_Telescope)pc->data;
6031e07b27eSBarry Smith   PetscErrorCode    ierr;
6041e07b27eSBarry Smith   Vec               xtmp,xred,yred;
60513c30530SDave May   PetscInt          i,st,ed;
6061e07b27eSBarry Smith   VecScatter        scatter;
6071e07b27eSBarry Smith   PetscScalar       *array;
6081e07b27eSBarry Smith   const PetscScalar *x_array;
6091e07b27eSBarry Smith 
6101e07b27eSBarry Smith   PetscFunctionBegin;
611bf00f589SPatrick Sanan   ierr = PetscCitationsRegister(citation,&cited);CHKERRQ(ierr);
612bf00f589SPatrick Sanan 
6131e07b27eSBarry Smith   xtmp    = sred->xtmp;
6141e07b27eSBarry Smith   scatter = sred->scatter;
6151e07b27eSBarry Smith   xred    = sred->xred;
6161e07b27eSBarry Smith   yred    = sred->yred;
6171e07b27eSBarry Smith 
6181e07b27eSBarry Smith   /* pull in vector x->xtmp */
6191e07b27eSBarry Smith   ierr = VecScatterBegin(scatter,x,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6201e07b27eSBarry Smith   ierr = VecScatterEnd(scatter,x,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6211e07b27eSBarry Smith 
622bf00f589SPatrick Sanan   /* copy vector entries into xred */
6231e07b27eSBarry Smith   ierr = VecGetArrayRead(xtmp,&x_array);CHKERRQ(ierr);
6241e07b27eSBarry Smith   if (xred) {
6251e07b27eSBarry Smith     PetscScalar *LA_xred;
6261e07b27eSBarry Smith     ierr = VecGetOwnershipRange(xred,&st,&ed);CHKERRQ(ierr);
6271e07b27eSBarry Smith     ierr = VecGetArray(xred,&LA_xred);CHKERRQ(ierr);
6281e07b27eSBarry Smith     for (i=0; i<ed-st; i++) {
6291e07b27eSBarry Smith       LA_xred[i] = x_array[i];
6301e07b27eSBarry Smith     }
6311e07b27eSBarry Smith     ierr = VecRestoreArray(xred,&LA_xred);CHKERRQ(ierr);
6321e07b27eSBarry Smith   }
6331e07b27eSBarry Smith   ierr = VecRestoreArrayRead(xtmp,&x_array);CHKERRQ(ierr);
6341e07b27eSBarry Smith   /* solve */
63557f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
6361e07b27eSBarry Smith     ierr = KSPSolve(sred->ksp,xred,yred);CHKERRQ(ierr);
637c0decd05SBarry Smith     ierr = KSPCheckSolve(sred->ksp,pc,yred);CHKERRQ(ierr);
6381e07b27eSBarry Smith   }
6391e07b27eSBarry Smith   /* return vector */
6401e07b27eSBarry Smith   ierr = VecGetArray(xtmp,&array);CHKERRQ(ierr);
6411e07b27eSBarry Smith   if (yred) {
6421e07b27eSBarry Smith     const PetscScalar *LA_yred;
6431e07b27eSBarry Smith     ierr = VecGetOwnershipRange(yred,&st,&ed);CHKERRQ(ierr);
6441e07b27eSBarry Smith     ierr = VecGetArrayRead(yred,&LA_yred);CHKERRQ(ierr);
6451e07b27eSBarry Smith     for (i=0; i<ed-st; i++) {
6461e07b27eSBarry Smith       array[i] = LA_yred[i];
6471e07b27eSBarry Smith     }
6481e07b27eSBarry Smith     ierr = VecRestoreArrayRead(yred,&LA_yred);CHKERRQ(ierr);
6491e07b27eSBarry Smith   }
6501e07b27eSBarry Smith   ierr = VecRestoreArray(xtmp,&array);CHKERRQ(ierr);
6511e07b27eSBarry Smith   ierr = VecScatterBegin(scatter,xtmp,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6521e07b27eSBarry Smith   ierr = VecScatterEnd(scatter,xtmp,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
6531e07b27eSBarry Smith   PetscFunctionReturn(0);
6541e07b27eSBarry Smith }
6551e07b27eSBarry Smith 
656f650675bSDave 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)
657f650675bSDave May {
658f650675bSDave May   PC_Telescope      sred = (PC_Telescope)pc->data;
659f650675bSDave May   PetscErrorCode    ierr;
660a1d91a28SDave May   Vec               xtmp,yred;
661f650675bSDave May   PetscInt          i,st,ed;
662f650675bSDave May   VecScatter        scatter;
663f650675bSDave May   const PetscScalar *x_array;
664f650675bSDave May   PetscBool         default_init_guess_value;
665f650675bSDave May 
666f650675bSDave May   PetscFunctionBegin;
667f650675bSDave May   xtmp    = sred->xtmp;
668f650675bSDave May   scatter = sred->scatter;
669f650675bSDave May   yred    = sred->yred;
670f650675bSDave May 
671*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(its > 1,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCApplyRichardson_Telescope only supports max_it = 1");
672f650675bSDave May   *reason = (PCRichardsonConvergedReason)0;
673f650675bSDave May 
674f650675bSDave May   if (!zeroguess) {
675f650675bSDave May     ierr = PetscInfo(pc,"PCTelescope: Scattering y for non-zero initial guess\n");CHKERRQ(ierr);
676f650675bSDave May     /* pull in vector y->xtmp */
677f650675bSDave May     ierr = VecScatterBegin(scatter,y,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
678f650675bSDave May     ierr = VecScatterEnd(scatter,y,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
679f650675bSDave May 
680bf00f589SPatrick Sanan     /* copy vector entries into xred */
681f650675bSDave May     ierr = VecGetArrayRead(xtmp,&x_array);CHKERRQ(ierr);
682f650675bSDave May     if (yred) {
683f650675bSDave May       PetscScalar *LA_yred;
684f650675bSDave May       ierr = VecGetOwnershipRange(yred,&st,&ed);CHKERRQ(ierr);
685f650675bSDave May       ierr = VecGetArray(yred,&LA_yred);CHKERRQ(ierr);
686f650675bSDave May       for (i=0; i<ed-st; i++) {
687f650675bSDave May         LA_yred[i] = x_array[i];
688f650675bSDave May       }
689f650675bSDave May       ierr = VecRestoreArray(yred,&LA_yred);CHKERRQ(ierr);
690f650675bSDave May     }
691f650675bSDave May     ierr = VecRestoreArrayRead(xtmp,&x_array);CHKERRQ(ierr);
692f650675bSDave May   }
693f650675bSDave May 
69457f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
695f650675bSDave May     ierr = KSPGetInitialGuessNonzero(sred->ksp,&default_init_guess_value);CHKERRQ(ierr);
69660d4fc61SSatish Balay     if (!zeroguess) {ierr = KSPSetInitialGuessNonzero(sred->ksp,PETSC_TRUE);CHKERRQ(ierr);}
697f650675bSDave May   }
698f650675bSDave May 
699f650675bSDave May   ierr = PCApply_Telescope(pc,x,y);CHKERRQ(ierr);
700f650675bSDave May 
70157f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
702f650675bSDave May     ierr = KSPSetInitialGuessNonzero(sred->ksp,default_init_guess_value);CHKERRQ(ierr);
703f650675bSDave May   }
704f650675bSDave May 
705f650675bSDave May   if (!*reason) *reason = PCRICHARDSON_CONVERGED_ITS;
706f650675bSDave May   *outits = 1;
707f650675bSDave May   PetscFunctionReturn(0);
708f650675bSDave May }
709f650675bSDave May 
7101e07b27eSBarry Smith static PetscErrorCode PCReset_Telescope(PC pc)
7111e07b27eSBarry Smith {
7121e07b27eSBarry Smith   PC_Telescope   sred = (PC_Telescope)pc->data;
7131e07b27eSBarry Smith   PetscErrorCode ierr;
7141e07b27eSBarry Smith 
715362febeeSStefano Zampini   PetscFunctionBegin;
7161e07b27eSBarry Smith   ierr = ISDestroy(&sred->isin);CHKERRQ(ierr);
7171e07b27eSBarry Smith   ierr = VecScatterDestroy(&sred->scatter);CHKERRQ(ierr);
718e3acf2f7SBarry Smith   ierr = VecDestroy(&sred->xred);CHKERRQ(ierr);
719e3acf2f7SBarry Smith   ierr = VecDestroy(&sred->yred);CHKERRQ(ierr);
720e3acf2f7SBarry Smith   ierr = VecDestroy(&sred->xtmp);CHKERRQ(ierr);
721e3acf2f7SBarry Smith   ierr = MatDestroy(&sred->Bred);CHKERRQ(ierr);
722e3acf2f7SBarry Smith   ierr = KSPReset(sred->ksp);CHKERRQ(ierr);
7231e07b27eSBarry Smith   if (sred->pctelescope_reset_type) {
7241e07b27eSBarry Smith     ierr = sred->pctelescope_reset_type(pc);CHKERRQ(ierr);
7251e07b27eSBarry Smith   }
7261e07b27eSBarry Smith   PetscFunctionReturn(0);
7271e07b27eSBarry Smith }
7281e07b27eSBarry Smith 
7291e07b27eSBarry Smith static PetscErrorCode PCDestroy_Telescope(PC pc)
7301e07b27eSBarry Smith {
7311e07b27eSBarry Smith   PC_Telescope   sred = (PC_Telescope)pc->data;
7321e07b27eSBarry Smith   PetscErrorCode ierr;
7331e07b27eSBarry Smith 
7341e07b27eSBarry Smith   PetscFunctionBegin;
7351e07b27eSBarry Smith   ierr = PCReset_Telescope(pc);CHKERRQ(ierr);
736e3acf2f7SBarry Smith   ierr = KSPDestroy(&sred->ksp);CHKERRQ(ierr);
7371e07b27eSBarry Smith   ierr = PetscSubcommDestroy(&sred->psubcomm);CHKERRQ(ierr);
738e3acf2f7SBarry Smith   ierr = PetscFree(sred->dm_ctx);CHKERRQ(ierr);
739e3acf2f7SBarry Smith   ierr = PetscFree(pc->data);CHKERRQ(ierr);
7401e07b27eSBarry Smith   PetscFunctionReturn(0);
7411e07b27eSBarry Smith }
7421e07b27eSBarry Smith 
7434416b707SBarry Smith static PetscErrorCode PCSetFromOptions_Telescope(PetscOptionItems *PetscOptionsObject,PC pc)
7441e07b27eSBarry Smith {
7451e07b27eSBarry Smith   PC_Telescope     sred = (PC_Telescope)pc->data;
7461e07b27eSBarry Smith   PetscErrorCode   ierr;
7471e07b27eSBarry Smith   MPI_Comm         comm;
7481e07b27eSBarry Smith   PetscMPIInt      size;
74948a10b22SPatrick Sanan   PetscBool        flg;
75048a10b22SPatrick Sanan   PetscSubcommType subcommtype;
7511e07b27eSBarry Smith 
7521e07b27eSBarry Smith   PetscFunctionBegin;
7531e07b27eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
754ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
7551e07b27eSBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"Telescope options");CHKERRQ(ierr);
75648a10b22SPatrick Sanan   ierr = PetscOptionsEnum("-pc_telescope_subcomm_type","Subcomm type (interlaced or contiguous)","PCTelescopeSetSubcommType",PetscSubcommTypes,(PetscEnum)sred->subcommtype,(PetscEnum*)&subcommtype,&flg);CHKERRQ(ierr);
75748a10b22SPatrick Sanan   if (flg) {
75848a10b22SPatrick Sanan     ierr = PCTelescopeSetSubcommType(pc,subcommtype);CHKERRQ(ierr);
75948a10b22SPatrick Sanan   }
7600a545947SLisandro Dalcin   ierr = PetscOptionsInt("-pc_telescope_reduction_factor","Factor to reduce comm size by","PCTelescopeSetReductionFactor",sred->redfactor,&sred->redfactor,NULL);CHKERRQ(ierr);
761*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(sred->redfactor > size,comm,PETSC_ERR_ARG_WRONG,"-pc_telescope_reduction_factor <= comm size");
7620a545947SLisandro Dalcin   ierr = PetscOptionsBool("-pc_telescope_ignore_dm","Ignore any DM attached to the PC","PCTelescopeSetIgnoreDM",sred->ignore_dm,&sred->ignore_dm,NULL);CHKERRQ(ierr);
7630a545947SLisandro Dalcin   ierr = PetscOptionsBool("-pc_telescope_ignore_kspcomputeoperators","Ignore method used to compute A","PCTelescopeSetIgnoreKSPComputeOperators",sred->ignore_kspcomputeoperators,&sred->ignore_kspcomputeoperators,NULL);CHKERRQ(ierr);
7640a545947SLisandro Dalcin   ierr = PetscOptionsBool("-pc_telescope_use_coarse_dm","Define sub-communicator from the coarse DM","PCTelescopeSetUseCoarseDM",sred->use_coarse_dm,&sred->use_coarse_dm,NULL);CHKERRQ(ierr);
7651e07b27eSBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
7661e07b27eSBarry Smith   PetscFunctionReturn(0);
7671e07b27eSBarry Smith }
7681e07b27eSBarry Smith 
7691e07b27eSBarry Smith /* PC simplementation specific API's */
7701e07b27eSBarry Smith 
7711e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetKSP_Telescope(PC pc,KSP *ksp)
7721e07b27eSBarry Smith {
7731e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
774bd49479cSSatish Balay   PetscFunctionBegin;
7751e07b27eSBarry Smith   if (ksp) *ksp = red->ksp;
776bd49479cSSatish Balay   PetscFunctionReturn(0);
7771e07b27eSBarry Smith }
7781e07b27eSBarry Smith 
77948a10b22SPatrick Sanan static PetscErrorCode PCTelescopeGetSubcommType_Telescope(PC pc,PetscSubcommType *subcommtype)
78048a10b22SPatrick Sanan {
78148a10b22SPatrick Sanan   PC_Telescope red = (PC_Telescope)pc->data;
78248a10b22SPatrick Sanan   PetscFunctionBegin;
78348a10b22SPatrick Sanan   if (subcommtype) *subcommtype = red->subcommtype;
78448a10b22SPatrick Sanan   PetscFunctionReturn(0);
78548a10b22SPatrick Sanan }
78648a10b22SPatrick Sanan 
78748a10b22SPatrick Sanan static PetscErrorCode PCTelescopeSetSubcommType_Telescope(PC pc,PetscSubcommType subcommtype)
78848a10b22SPatrick Sanan {
78948a10b22SPatrick Sanan   PC_Telescope     red = (PC_Telescope)pc->data;
79048a10b22SPatrick Sanan 
79148a10b22SPatrick Sanan   PetscFunctionBegin;
792*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(pc->setupcalled,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"You cannot change the subcommunicator type for PCTelescope after it has been set up.");
79348a10b22SPatrick Sanan   red->subcommtype = subcommtype;
79448a10b22SPatrick Sanan   PetscFunctionReturn(0);
79548a10b22SPatrick Sanan }
79648a10b22SPatrick Sanan 
7971e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetReductionFactor_Telescope(PC pc,PetscInt *fact)
7981e07b27eSBarry Smith {
7991e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
800bd49479cSSatish Balay   PetscFunctionBegin;
8011e07b27eSBarry Smith   if (fact) *fact = red->redfactor;
802bd49479cSSatish Balay   PetscFunctionReturn(0);
8031e07b27eSBarry Smith }
8041e07b27eSBarry Smith 
8051e07b27eSBarry Smith static PetscErrorCode PCTelescopeSetReductionFactor_Telescope(PC pc,PetscInt fact)
8061e07b27eSBarry Smith {
8071e07b27eSBarry Smith   PC_Telescope     red = (PC_Telescope)pc->data;
8081e07b27eSBarry Smith   PetscMPIInt      size;
8091e07b27eSBarry Smith   PetscErrorCode   ierr;
8101e07b27eSBarry Smith 
811bd49479cSSatish Balay   PetscFunctionBegin;
812ffc4695bSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRMPI(ierr);
813*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(fact <= 0,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Reduction factor of telescoping PC %D must be positive",fact);
814*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(fact > size,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Reduction factor of telescoping PC %D must be <= comm.size",fact);
8151e07b27eSBarry Smith   red->redfactor = fact;
816bd49479cSSatish Balay   PetscFunctionReturn(0);
8171e07b27eSBarry Smith }
8181e07b27eSBarry Smith 
8191e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetIgnoreDM_Telescope(PC pc,PetscBool *v)
8201e07b27eSBarry Smith {
8211e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
822bd49479cSSatish Balay   PetscFunctionBegin;
8231e07b27eSBarry Smith   if (v) *v = red->ignore_dm;
824bd49479cSSatish Balay   PetscFunctionReturn(0);
8251e07b27eSBarry Smith }
82648a10b22SPatrick Sanan 
8271e07b27eSBarry Smith static PetscErrorCode PCTelescopeSetIgnoreDM_Telescope(PC pc,PetscBool v)
8281e07b27eSBarry Smith {
8291e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
830bd49479cSSatish Balay   PetscFunctionBegin;
8311e07b27eSBarry Smith   red->ignore_dm = v;
832bd49479cSSatish Balay   PetscFunctionReturn(0);
8331e07b27eSBarry Smith }
8341e07b27eSBarry Smith 
8358d9f7141SDave May static PetscErrorCode PCTelescopeGetUseCoarseDM_Telescope(PC pc,PetscBool *v)
8368d9f7141SDave May {
8378d9f7141SDave May   PC_Telescope red = (PC_Telescope)pc->data;
8388d9f7141SDave May   PetscFunctionBegin;
8398d9f7141SDave May   if (v) *v = red->use_coarse_dm;
8408d9f7141SDave May   PetscFunctionReturn(0);
8418d9f7141SDave May }
8428d9f7141SDave May 
8438d9f7141SDave May static PetscErrorCode PCTelescopeSetUseCoarseDM_Telescope(PC pc,PetscBool v)
8448d9f7141SDave May {
8458d9f7141SDave May   PC_Telescope red = (PC_Telescope)pc->data;
8468d9f7141SDave May   PetscFunctionBegin;
8478d9f7141SDave May   red->use_coarse_dm = v;
8488d9f7141SDave May   PetscFunctionReturn(0);
8498d9f7141SDave May }
8508d9f7141SDave May 
8510ae7c45bSDave May static PetscErrorCode PCTelescopeGetIgnoreKSPComputeOperators_Telescope(PC pc,PetscBool *v)
8520ae7c45bSDave May {
8530ae7c45bSDave May   PC_Telescope red = (PC_Telescope)pc->data;
8540ae7c45bSDave May   PetscFunctionBegin;
8550ae7c45bSDave May   if (v) *v = red->ignore_kspcomputeoperators;
8560ae7c45bSDave May   PetscFunctionReturn(0);
8570ae7c45bSDave May }
85848a10b22SPatrick Sanan 
8590ae7c45bSDave May static PetscErrorCode PCTelescopeSetIgnoreKSPComputeOperators_Telescope(PC pc,PetscBool v)
8600ae7c45bSDave May {
8610ae7c45bSDave May   PC_Telescope red = (PC_Telescope)pc->data;
8620ae7c45bSDave May   PetscFunctionBegin;
8630ae7c45bSDave May   red->ignore_kspcomputeoperators = v;
8640ae7c45bSDave May   PetscFunctionReturn(0);
8650ae7c45bSDave May }
8660ae7c45bSDave May 
8671e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetDM_Telescope(PC pc,DM *dm)
8681e07b27eSBarry Smith {
8691e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
870bd49479cSSatish Balay   PetscFunctionBegin;
8711e07b27eSBarry Smith   *dm = private_PCTelescopeGetSubDM(red);
872bd49479cSSatish Balay   PetscFunctionReturn(0);
8731e07b27eSBarry Smith }
8741e07b27eSBarry Smith 
8751e07b27eSBarry Smith /*@
8761e07b27eSBarry Smith  PCTelescopeGetKSP - Gets the KSP created by the telescoping PC.
8771e07b27eSBarry Smith 
8781e07b27eSBarry Smith  Not Collective
8791e07b27eSBarry Smith 
8801e07b27eSBarry Smith  Input Parameter:
8811e07b27eSBarry Smith .  pc - the preconditioner context
8821e07b27eSBarry Smith 
8831e07b27eSBarry Smith  Output Parameter:
8841e07b27eSBarry Smith .  subksp - the KSP defined the smaller set of processes
8851e07b27eSBarry Smith 
8861e07b27eSBarry Smith  Level: advanced
8871e07b27eSBarry Smith 
8881e07b27eSBarry Smith @*/
8891e07b27eSBarry Smith PetscErrorCode PCTelescopeGetKSP(PC pc,KSP *subksp)
8901e07b27eSBarry Smith {
891bd49479cSSatish Balay   PetscErrorCode ierr;
892bd49479cSSatish Balay   PetscFunctionBegin;
893163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetKSP_C",(PC,KSP*),(pc,subksp));CHKERRQ(ierr);
894bd49479cSSatish Balay   PetscFunctionReturn(0);
8951e07b27eSBarry Smith }
8961e07b27eSBarry Smith 
8971e07b27eSBarry Smith /*@
8981e07b27eSBarry Smith  PCTelescopeGetReductionFactor - Gets the factor by which the original number of processes has been reduced by.
8991e07b27eSBarry Smith 
9001e07b27eSBarry Smith  Not Collective
9011e07b27eSBarry Smith 
9021e07b27eSBarry Smith  Input Parameter:
9031e07b27eSBarry Smith .  pc - the preconditioner context
9041e07b27eSBarry Smith 
9051e07b27eSBarry Smith  Output Parameter:
9061e07b27eSBarry Smith .  fact - the reduction factor
9071e07b27eSBarry Smith 
9081e07b27eSBarry Smith  Level: advanced
9091e07b27eSBarry Smith 
9101e07b27eSBarry Smith @*/
9111e07b27eSBarry Smith PetscErrorCode PCTelescopeGetReductionFactor(PC pc,PetscInt *fact)
9121e07b27eSBarry Smith {
913bd49479cSSatish Balay   PetscErrorCode ierr;
914bd49479cSSatish Balay   PetscFunctionBegin;
915163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetReductionFactor_C",(PC,PetscInt*),(pc,fact));CHKERRQ(ierr);
916bd49479cSSatish Balay   PetscFunctionReturn(0);
9171e07b27eSBarry Smith }
9181e07b27eSBarry Smith 
9191e07b27eSBarry Smith /*@
9201e07b27eSBarry Smith  PCTelescopeSetReductionFactor - Sets the factor by which the original number of processes has been reduced by.
9211e07b27eSBarry Smith 
9221e07b27eSBarry Smith  Not Collective
9231e07b27eSBarry Smith 
9241e07b27eSBarry Smith  Input Parameter:
9251e07b27eSBarry Smith .  pc - the preconditioner context
9261e07b27eSBarry Smith 
9271e07b27eSBarry Smith  Output Parameter:
9281e07b27eSBarry Smith .  fact - the reduction factor
9291e07b27eSBarry Smith 
9301e07b27eSBarry Smith  Level: advanced
9311e07b27eSBarry Smith 
9321e07b27eSBarry Smith @*/
9331e07b27eSBarry Smith PetscErrorCode PCTelescopeSetReductionFactor(PC pc,PetscInt fact)
9341e07b27eSBarry Smith {
935bd49479cSSatish Balay   PetscErrorCode ierr;
936bd49479cSSatish Balay   PetscFunctionBegin;
937bd49479cSSatish Balay   ierr = PetscTryMethod(pc,"PCTelescopeSetReductionFactor_C",(PC,PetscInt),(pc,fact));CHKERRQ(ierr);
938bd49479cSSatish Balay   PetscFunctionReturn(0);
9391e07b27eSBarry Smith }
9401e07b27eSBarry Smith 
9411e07b27eSBarry Smith /*@
9421e07b27eSBarry Smith  PCTelescopeGetIgnoreDM - Get the flag indicating if any DM attached to the PC will be used.
9431e07b27eSBarry Smith 
9441e07b27eSBarry Smith  Not Collective
9451e07b27eSBarry Smith 
9461e07b27eSBarry Smith  Input Parameter:
9471e07b27eSBarry Smith .  pc - the preconditioner context
9481e07b27eSBarry Smith 
9491e07b27eSBarry Smith  Output Parameter:
9501e07b27eSBarry Smith .  v - the flag
9511e07b27eSBarry Smith 
9521e07b27eSBarry Smith  Level: advanced
9531e07b27eSBarry Smith 
9541e07b27eSBarry Smith @*/
9551e07b27eSBarry Smith PetscErrorCode PCTelescopeGetIgnoreDM(PC pc,PetscBool *v)
9561e07b27eSBarry Smith {
957bd49479cSSatish Balay   PetscErrorCode ierr;
958bd49479cSSatish Balay   PetscFunctionBegin;
959163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetIgnoreDM_C",(PC,PetscBool*),(pc,v));CHKERRQ(ierr);
960bd49479cSSatish Balay   PetscFunctionReturn(0);
9611e07b27eSBarry Smith }
9621e07b27eSBarry Smith 
9631e07b27eSBarry Smith /*@
9641e07b27eSBarry Smith  PCTelescopeSetIgnoreDM - Set a flag to ignore any DM attached to the PC.
9651e07b27eSBarry Smith 
9661e07b27eSBarry Smith  Not Collective
9671e07b27eSBarry Smith 
9681e07b27eSBarry Smith  Input Parameter:
9691e07b27eSBarry Smith .  pc - the preconditioner context
9701e07b27eSBarry Smith 
9711e07b27eSBarry Smith  Output Parameter:
9721e07b27eSBarry Smith .  v - Use PETSC_TRUE to ignore any DM
9731e07b27eSBarry Smith 
9741e07b27eSBarry Smith  Level: advanced
9751e07b27eSBarry Smith 
9761e07b27eSBarry Smith @*/
977bfd6bcc6SSatish Balay PetscErrorCode PCTelescopeSetIgnoreDM(PC pc,PetscBool v)
9781e07b27eSBarry Smith {
979bd49479cSSatish Balay   PetscErrorCode ierr;
980bd49479cSSatish Balay   PetscFunctionBegin;
981bd49479cSSatish Balay   ierr = PetscTryMethod(pc,"PCTelescopeSetIgnoreDM_C",(PC,PetscBool),(pc,v));CHKERRQ(ierr);
982bd49479cSSatish Balay   PetscFunctionReturn(0);
9831e07b27eSBarry Smith }
9841e07b27eSBarry Smith 
9851e07b27eSBarry Smith /*@
9868d9f7141SDave May  PCTelescopeGetUseCoarseDM - Get the flag indicating if the coarse DM attached to DM associated with the PC will be used.
9878d9f7141SDave May 
9888d9f7141SDave May  Not Collective
9898d9f7141SDave May 
9908d9f7141SDave May  Input Parameter:
9918d9f7141SDave May .  pc - the preconditioner context
9928d9f7141SDave May 
9938d9f7141SDave May  Output Parameter:
9948d9f7141SDave May .  v - the flag
9958d9f7141SDave May 
9968d9f7141SDave May  Level: advanced
9978d9f7141SDave May 
9988d9f7141SDave May @*/
9998d9f7141SDave May PetscErrorCode PCTelescopeGetUseCoarseDM(PC pc,PetscBool *v)
10008d9f7141SDave May {
10018d9f7141SDave May   PetscErrorCode ierr;
10028d9f7141SDave May   PetscFunctionBegin;
10038d9f7141SDave May   ierr = PetscUseMethod(pc,"PCTelescopeGetUseCoarseDM_C",(PC,PetscBool*),(pc,v));CHKERRQ(ierr);
10048d9f7141SDave May   PetscFunctionReturn(0);
10058d9f7141SDave May }
10068d9f7141SDave May 
10078d9f7141SDave May /*@
10088d9f7141SDave May  PCTelescopeSetUseCoarseDM - Set a flag to query the DM attached to the PC if it also has a coarse DM
10098d9f7141SDave May 
10108d9f7141SDave May  Not Collective
10118d9f7141SDave May 
10128d9f7141SDave May  Input Parameter:
10138d9f7141SDave May .  pc - the preconditioner context
10148d9f7141SDave May 
10158d9f7141SDave May  Output Parameter:
1016aaa7a805SDave May .  v - Use PETSC_FALSE to ignore any coarse DM
10178d9f7141SDave May 
10188d9f7141SDave May  Notes:
10198d9f7141SDave May  When you have specified to use a coarse DM, the communicator used to create the sub-KSP within PCTelescope
10208d9f7141SDave May  will be that of the coarse DM. Hence the flags -pc_telescope_reduction_factor and
10218d9f7141SDave May  -pc_telescope_subcomm_type will no longer have any meaning.
10228d9f7141SDave May  It is required that the communicator associated with the parent (fine) and the coarse DM are of different sizes.
10238d9f7141SDave May  An error will occur of the size of the communicator associated with the coarse DM
10248d9f7141SDave May  is the same as that of the parent DM.
10258d9f7141SDave May  Furthermore, it is required that the communicator on the coarse DM is a sub-communicator of the parent.
10268d9f7141SDave May  This will be checked at the time the preconditioner is setup and an error will occur if
10278d9f7141SDave May  the coarse DM does not define a sub-communicator of that used by the parent DM.
10288d9f7141SDave May 
10298d9f7141SDave May  The particular Telescope setup invoked when using a coarse DM is agnostic with respect to the type of
10308d9f7141SDave May  the DM used (e.g. it supports DMSHELL, DMPLEX, etc).
10318d9f7141SDave May 
10328d9f7141SDave May  Support is currently only provided for the case when you are using KSPSetComputeOperators()
10338d9f7141SDave May 
10348d9f7141SDave May  The user is required to compose a function with the parent DM to facilitate the transfer of fields (Vec) between the different decompositions defined by the fine and coarse DMs.
10358d9f7141SDave May  In the user code, this is achieved via
10368d9f7141SDave May .vb
10378d9f7141SDave May    {
10388d9f7141SDave May      DM dm_fine;
10398d9f7141SDave May      PetscObjectCompose((PetscObject)dm_fine,"PCTelescopeFieldScatter",your_field_scatter_method);
10408d9f7141SDave May    }
10418d9f7141SDave May .ve
10428d9f7141SDave May  The signature of the user provided field scatter method is
10438d9f7141SDave May .vb
10448d9f7141SDave May    PetscErrorCode your_field_scatter_method(DM dm_fine,Vec x_fine,ScatterMode mode,DM dm_coarse,Vec x_coarse);
10458d9f7141SDave May .ve
10468d9f7141SDave May  The user must provide support for both mode = SCATTER_FORWARD and mode = SCATTER_REVERSE.
10478d9f7141SDave May  SCATTER_FORWARD implies the direction of transfer is from the parent (fine) DM to the coarse DM.
10488d9f7141SDave May 
10498d9f7141SDave May  Optionally, the user may also compose a function with the parent DM to facilitate the transfer
10508d9f7141SDave May  of state variables between the fine and coarse DMs.
10518d9f7141SDave May  In the context of a finite element discretization, an example state variable might be
10528d9f7141SDave May  values associated with quadrature points within each element.
10538d9f7141SDave May  A user provided state scatter method is composed via
10548d9f7141SDave May .vb
10558d9f7141SDave May    {
10568d9f7141SDave May      DM dm_fine;
10578d9f7141SDave May      PetscObjectCompose((PetscObject)dm_fine,"PCTelescopeStateScatter",your_state_scatter_method);
10588d9f7141SDave May    }
10598d9f7141SDave May .ve
10608d9f7141SDave May  The signature of the user provided state scatter method is
10618d9f7141SDave May .vb
10628d9f7141SDave May    PetscErrorCode your_state_scatter_method(DM dm_fine,ScatterMode mode,DM dm_coarse);
10638d9f7141SDave May .ve
10648d9f7141SDave May  SCATTER_FORWARD implies the direction of transfer is from the fine DM to the coarse DM.
10658d9f7141SDave May  The user is only required to support mode = SCATTER_FORWARD.
10668d9f7141SDave May  No assumption is made about the data type of the state variables.
10678d9f7141SDave May  These must be managed by the user and must be accessible from the DM.
10688d9f7141SDave May 
10698d9f7141SDave May  Care must be taken in defining the user context passed to KSPSetComputeOperators() which is to be
10708d9f7141SDave May  associated with the sub-KSP residing within PCTelescope.
10718d9f7141SDave May  In general, PCTelescope assumes that the context on the fine and coarse DM used with
10728d9f7141SDave May  KSPSetComputeOperators() should be "similar" in type or origin.
10738d9f7141SDave May  Specifically the following rules are used to infer what context on the sub-KSP should be.
10748d9f7141SDave May 
10758d9f7141SDave May  First the contexts from the KSP and the fine and coarse DMs are retrieved.
10768d9f7141SDave May  Note that the special case of a DMSHELL context is queried.
10778d9f7141SDave May 
10788d9f7141SDave May .vb
10798d9f7141SDave May    DMKSPGetComputeOperators(dm_fine,&dmfine_kspfunc,&dmfine_kspctx);
10808d9f7141SDave May    DMGetApplicationContext(dm_fine,&dmfine_appctx);
10818d9f7141SDave May    DMShellGetContext(dm_fine,&dmfine_shellctx);
10828d9f7141SDave May 
10838d9f7141SDave May    DMGetApplicationContext(dm_coarse,&dmcoarse_appctx);
10848d9f7141SDave May    DMShellGetContext(dm_coarse,&dmcoarse_shellctx);
10858d9f7141SDave May .ve
10868d9f7141SDave May 
10878d9f7141SDave May  The following rules are then enforced:
10888d9f7141SDave May 
10898d9f7141SDave May  1. If dmfine_kspctx = NULL, then we provide a NULL pointer as the context for the sub-KSP:
10908d9f7141SDave May  KSPSetComputeOperators(sub_ksp,dmfine_kspfunc,NULL);
10918d9f7141SDave May 
10928d9f7141SDave May  2. If dmfine_kspctx != NULL and dmfine_kspctx == dmfine_appctx,
10938d9f7141SDave May  check that dmcoarse_appctx is also non-NULL. If this is true, then:
10948d9f7141SDave May  KSPSetComputeOperators(sub_ksp,dmfine_kspfunc,dmcoarse_appctx);
10958d9f7141SDave May 
10968d9f7141SDave May  3. If dmfine_kspctx != NULL and dmfine_kspctx == dmfine_shellctx,
10978d9f7141SDave May  check that dmcoarse_shellctx is also non-NULL. If this is true, then:
10988d9f7141SDave May  KSPSetComputeOperators(sub_ksp,dmfine_kspfunc,dmcoarse_shellctx);
10998d9f7141SDave May 
11008d9f7141SDave May  If neither of the above three tests passed, then PCTelescope cannot safely determine what
11018d9f7141SDave May  context should be provided to KSPSetComputeOperators() for use with the sub-KSP.
11028d9f7141SDave May  In this case, an additional mechanism is provided via a composed function which will return
11038d9f7141SDave May  the actual context to be used. To use this feature you must compose the "getter" function
11048d9f7141SDave May  with the coarse DM, e.g.
11058d9f7141SDave May .vb
11068d9f7141SDave May    {
11078d9f7141SDave May      DM dm_coarse;
11088d9f7141SDave May      PetscObjectCompose((PetscObject)dm_coarse,"PCTelescopeGetCoarseDMKSPContext",your_coarse_context_getter);
11098d9f7141SDave May    }
11108d9f7141SDave May .ve
11118d9f7141SDave May  The signature of the user provided method is
11128d9f7141SDave May .vb
11138d9f7141SDave May    PetscErrorCode your_coarse_context_getter(DM dm_coarse,void **your_kspcontext);
11148d9f7141SDave May .ve
11158d9f7141SDave May 
11168d9f7141SDave May  Level: advanced
11178d9f7141SDave May 
11188d9f7141SDave May @*/
11198d9f7141SDave May PetscErrorCode PCTelescopeSetUseCoarseDM(PC pc,PetscBool v)
11208d9f7141SDave May {
11218d9f7141SDave May   PetscErrorCode ierr;
11228d9f7141SDave May   PetscFunctionBegin;
11238d9f7141SDave May   ierr = PetscTryMethod(pc,"PCTelescopeSetUseCoarseDM_C",(PC,PetscBool),(pc,v));CHKERRQ(ierr);
11248d9f7141SDave May   PetscFunctionReturn(0);
11258d9f7141SDave May }
11268d9f7141SDave May 
11278d9f7141SDave May /*@
11280ae7c45bSDave May  PCTelescopeGetIgnoreKSPComputeOperators - Get the flag indicating if KSPComputeOperators will be used.
11290ae7c45bSDave May 
11300ae7c45bSDave May  Not Collective
11310ae7c45bSDave May 
11320ae7c45bSDave May  Input Parameter:
11330ae7c45bSDave May .  pc - the preconditioner context
11340ae7c45bSDave May 
11350ae7c45bSDave May  Output Parameter:
11360ae7c45bSDave May .  v - the flag
11370ae7c45bSDave May 
11380ae7c45bSDave May  Level: advanced
11390ae7c45bSDave May 
11400ae7c45bSDave May @*/
11410ae7c45bSDave May PetscErrorCode PCTelescopeGetIgnoreKSPComputeOperators(PC pc,PetscBool *v)
11420ae7c45bSDave May {
11430ae7c45bSDave May   PetscErrorCode ierr;
11440ae7c45bSDave May   PetscFunctionBegin;
1145163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetIgnoreKSPComputeOperators_C",(PC,PetscBool*),(pc,v));CHKERRQ(ierr);
11460ae7c45bSDave May   PetscFunctionReturn(0);
11470ae7c45bSDave May }
11480ae7c45bSDave May 
11490ae7c45bSDave May /*@
11500ae7c45bSDave May  PCTelescopeSetIgnoreKSPComputeOperators - Set a flag to ignore KSPComputeOperators.
11510ae7c45bSDave May 
11520ae7c45bSDave May  Not Collective
11530ae7c45bSDave May 
11540ae7c45bSDave May  Input Parameter:
11550ae7c45bSDave May .  pc - the preconditioner context
11560ae7c45bSDave May 
11570ae7c45bSDave May  Output Parameter:
1158a954d8f4SDave May .  v - Use PETSC_TRUE to ignore the method (if defined) set via KSPSetComputeOperators on pc
11590ae7c45bSDave May 
11600ae7c45bSDave May  Level: advanced
11610ae7c45bSDave May 
11620ae7c45bSDave May @*/
11630ae7c45bSDave May PetscErrorCode PCTelescopeSetIgnoreKSPComputeOperators(PC pc,PetscBool v)
11640ae7c45bSDave May {
11650ae7c45bSDave May   PetscErrorCode ierr;
11660ae7c45bSDave May   PetscFunctionBegin;
11670ae7c45bSDave May   ierr = PetscTryMethod(pc,"PCTelescopeSetIgnoreKSPComputeOperators_C",(PC,PetscBool),(pc,v));CHKERRQ(ierr);
11680ae7c45bSDave May   PetscFunctionReturn(0);
11690ae7c45bSDave May }
11700ae7c45bSDave May 
11710ae7c45bSDave May /*@
11721e07b27eSBarry Smith  PCTelescopeGetDM - Get the re-partitioned DM attached to the sub KSP.
11731e07b27eSBarry Smith 
11741e07b27eSBarry Smith  Not Collective
11751e07b27eSBarry Smith 
11761e07b27eSBarry Smith  Input Parameter:
11771e07b27eSBarry Smith .  pc - the preconditioner context
11781e07b27eSBarry Smith 
11791e07b27eSBarry Smith  Output Parameter:
11801e07b27eSBarry Smith .  subdm - The re-partitioned DM
11811e07b27eSBarry Smith 
11821e07b27eSBarry Smith  Level: advanced
11831e07b27eSBarry Smith 
11841e07b27eSBarry Smith @*/
11851e07b27eSBarry Smith PetscErrorCode PCTelescopeGetDM(PC pc,DM *subdm)
11861e07b27eSBarry Smith {
1187bd49479cSSatish Balay   PetscErrorCode ierr;
1188bd49479cSSatish Balay   PetscFunctionBegin;
1189163d334eSBarry Smith   ierr = PetscUseMethod(pc,"PCTelescopeGetDM_C",(PC,DM*),(pc,subdm));CHKERRQ(ierr);
1190bd49479cSSatish Balay   PetscFunctionReturn(0);
11911e07b27eSBarry Smith }
11921e07b27eSBarry Smith 
119348a10b22SPatrick Sanan /*@
119448a10b22SPatrick Sanan  PCTelescopeSetSubcommType - set subcommunicator type (interlaced or contiguous)
119548a10b22SPatrick Sanan 
119648a10b22SPatrick Sanan  Logically Collective
119748a10b22SPatrick Sanan 
1198d8d19677SJose E. Roman  Input Parameters:
11991dae98e4SBarry Smith +  pc - the preconditioner context
12001dae98e4SBarry Smith -  subcommtype - the subcommunicator type (see PetscSubcommType)
120148a10b22SPatrick Sanan 
120248a10b22SPatrick Sanan  Level: advanced
120348a10b22SPatrick Sanan 
120448a10b22SPatrick Sanan .seealso: PetscSubcommType, PetscSubcomm, PCTELESCOPE
120548a10b22SPatrick Sanan @*/
120648a10b22SPatrick Sanan PetscErrorCode PCTelescopeSetSubcommType(PC pc, PetscSubcommType subcommtype)
120748a10b22SPatrick Sanan {
120848a10b22SPatrick Sanan   PetscErrorCode ierr;
120948a10b22SPatrick Sanan   PetscFunctionBegin;
121048a10b22SPatrick Sanan   ierr = PetscTryMethod(pc,"PCTelescopeSetSubcommType_C",(PC,PetscSubcommType),(pc,subcommtype));CHKERRQ(ierr);
121148a10b22SPatrick Sanan   PetscFunctionReturn(0);
121248a10b22SPatrick Sanan }
121348a10b22SPatrick Sanan 
121448a10b22SPatrick Sanan /*@
121548a10b22SPatrick Sanan  PCTelescopeGetSubcommType - Get the subcommunicator type (interlaced or contiguous)
121648a10b22SPatrick Sanan 
121748a10b22SPatrick Sanan  Not Collective
121848a10b22SPatrick Sanan 
121948a10b22SPatrick Sanan  Input Parameter:
122048a10b22SPatrick Sanan .  pc - the preconditioner context
122148a10b22SPatrick Sanan 
122248a10b22SPatrick Sanan  Output Parameter:
122348a10b22SPatrick Sanan .  subcommtype - the subcommunicator type (see PetscSubcommType)
122448a10b22SPatrick Sanan 
122548a10b22SPatrick Sanan  Level: advanced
122648a10b22SPatrick Sanan 
12271dae98e4SBarry Smith .seealso: PetscSubcomm, PetscSubcommType, PCTELESCOPE
122848a10b22SPatrick Sanan @*/
12291dae98e4SBarry Smith PetscErrorCode PCTelescopeGetSubcommType(PC pc, PetscSubcommType *subcommtype)
123048a10b22SPatrick Sanan {
123148a10b22SPatrick Sanan   PetscErrorCode ierr;
123248a10b22SPatrick Sanan   PetscFunctionBegin;
123348a10b22SPatrick Sanan   ierr = PetscUseMethod(pc,"PCTelescopeGetSubcommType_C",(PC,PetscSubcommType*),(pc,subcommtype));CHKERRQ(ierr);
123448a10b22SPatrick Sanan   PetscFunctionReturn(0);
123548a10b22SPatrick Sanan }
123648a10b22SPatrick Sanan 
12371e07b27eSBarry Smith /* -------------------------------------------------------------------------------------*/
12381e07b27eSBarry Smith /*MC
123900fea0ebSDave May    PCTELESCOPE - Runs a KSP solver on a sub-communicator. MPI ranks not in the sub-communicator are idle during the solve.
12401e07b27eSBarry Smith 
12411e07b27eSBarry Smith    Options Database:
124200fea0ebSDave May +  -pc_telescope_reduction_factor <r> - factor to reduce the communicator size by. e.g. with 64 MPI ranks and r=4, the new sub-communicator will have 64/4 = 16 ranks.
124300fea0ebSDave May .  -pc_telescope_ignore_dm  - flag to indicate whether an attached DM should be ignored.
124400fea0ebSDave May .  -pc_telescope_subcomm_type <interlaced,contiguous> - defines the selection of MPI ranks on the sub-communicator. see PetscSubcomm for more information.
124500fea0ebSDave May .  -pc_telescope_ignore_kspcomputeoperators - flag to indicate whether KSPSetComputeOperators should be used on the sub-KSP.
124600fea0ebSDave May -  -pc_telescope_use_coarse_dm - flag to indicate whether the coarse DM should be used to define the sub-communicator.
12471e07b27eSBarry Smith 
12481e07b27eSBarry Smith    Level: advanced
12491e07b27eSBarry Smith 
12501e07b27eSBarry Smith    Notes:
125100fea0ebSDave May    Assuming that the parent preconditioner (PC) is defined on a communicator c, this implementation
125200fea0ebSDave May    creates a child sub-communicator (c') containing fewer MPI ranks than the original parent preconditioner (PC).
12536fc41876SBarry Smith    The preconditioner is deemed telescopic as it only calls KSPSolve() on a single
12548439623fSPatrick Sanan    sub-communicator, in contrast with PCREDUNDANT which calls KSPSolve() on N sub-communicators.
125500fea0ebSDave May    This means there will be MPI ranks which will be idle during the application of this preconditioner.
125600fea0ebSDave May    Additionally, in comparison with PCREDUNDANT, PCTELESCOPE can utilize an attached DM.
12576fc41876SBarry Smith 
125800fea0ebSDave May    The default type of the sub KSP (the KSP defined on c') is PREONLY.
125900fea0ebSDave May 
126000fea0ebSDave May    There are three setup mechanisms for PCTelescope. Features support by each type are described below.
126100fea0ebSDave May    In the following, we will refer to the operators B and B', these are the Bmat provided to the KSP on the
126200fea0ebSDave May    communicators c and c' respectively.
126300fea0ebSDave May 
126400fea0ebSDave May    [1] Default setup
126500fea0ebSDave May    The sub-communicator c' is created via PetscSubcommCreate().
1266a5b23f4aSJose E. Roman    Explicitly defined nullspace and near nullspace vectors will be propagated from B to B'.
126700fea0ebSDave May    Currently there is no support define nullspaces via a user supplied method (e.g. as passed to MatNullSpaceSetFunction()).
126800fea0ebSDave May    No support is provided for KSPSetComputeOperators().
126900fea0ebSDave May    Currently there is no support for the flag -pc_use_amat.
127000fea0ebSDave May 
127100fea0ebSDave May    [2] DM aware setup
127200fea0ebSDave May    If a DM is attached to the PC, it is re-partitioned on the sub-communicator c'.
127300fea0ebSDave May    c' is created via PetscSubcommCreate().
12741e07b27eSBarry Smith    Both the Bmat operator and the right hand side vector are permuted into the new DOF ordering defined by the re-partitioned DM.
12751e07b27eSBarry Smith    Currently only support for re-partitioning a DMDA is provided.
127600fea0ebSDave May    Any explicitly defined nullspace or near nullspace vectors attached to the original Bmat operator (B) are extracted, re-partitioned and set on the re-partitioned Bmat operator (B').
127700fea0ebSDave May    Currently there is no support define nullspaces via a user supplied method (e.g. as passed to MatNullSpaceSetFunction()).
127800fea0ebSDave May    Support is provided for KSPSetComputeOperators(). The user provided function and context is propagated to the sub KSP.
127900fea0ebSDave May    This is fragile since the user must ensure that their user context is valid for use on c'.
128000fea0ebSDave May    Currently there is no support for the flag -pc_use_amat.
12811e07b27eSBarry Smith 
128200fea0ebSDave May    [3] Coarse DM setup
128300fea0ebSDave May    If a DM (dmfine) is attached to the PC, dmfine is queried for a "coarse" DM (call this dmcoarse) via DMGetCoarseDM().
128400fea0ebSDave May    PCTELESCOPE will interpret the coarse DM as being defined on a sub-communicator of c.
128500fea0ebSDave May    The communicator associated with dmcoarse will define the c' to be used within PCTELESCOPE.
128600fea0ebSDave May    PCTELESCOPE will check that c' is in fact a sub-communicator of c. If it is not, an error will be reported.
128700fea0ebSDave May    The intention of this setup type is that PCTELESCOPE will use an existing (e.g. user defined) communicator hierarchy, say as would be
128800fea0ebSDave May    available with using multi-grid on unstructured meshes.
128900fea0ebSDave May    This setup will not use the command line options -pc_telescope_reduction_factor or -pc_telescope_subcomm_type.
129000fea0ebSDave May    Any explicitly defined nullspace or near nullspace vectors attached to the original Bmat operator (B) are extracted, scattered into the correct ordering consistent with dmcoarse and set on B'.
129100fea0ebSDave May    Currently there is no support define nullspaces via a user supplied method (e.g. as passed to MatNullSpaceSetFunction()).
129200fea0ebSDave May    There is no general method to permute field orderings, hence only KSPSetComputeOperators() is supported.
129300fea0ebSDave May    The user must use PetscObjectComposeFunction() with dmfine to define the method to scatter fields from dmfine to dmcoarse.
1294a5b23f4aSJose E. Roman    Propagation of the user context for KSPSetComputeOperators() on the sub KSP is attempted by querying the DM contexts associated with dmfine and dmcoarse. Alternatively, the user may use PetscObjectComposeFunction() with dmcoarse to define a method which will return the appropriate user context for KSPSetComputeOperators().
129500fea0ebSDave May    Currently there is no support for the flag -pc_use_amat.
129600fea0ebSDave May    This setup can be invoked by the option -pc_telescope_use_coarse_dm or by calling PCTelescopeSetUseCoarseDM(pc,PETSC_TRUE);
129700fea0ebSDave May    Further information about the user-provided methods required by this setup type are described here PCTelescopeSetUseCoarseDM().
12986fc41876SBarry Smith 
12996fc41876SBarry Smith    Developer Notes:
13006fc41876SBarry Smith    During PCSetup, the B operator is scattered onto c'.
13016fc41876SBarry Smith    Within PCApply, the RHS vector (x) is scattered into a redundant vector, xred (defined on c').
13028439623fSPatrick Sanan    Then, KSPSolve() is executed on the c' communicator.
13036fc41876SBarry Smith 
13046fc41876SBarry Smith    The communicator used within the telescoping preconditioner is defined by a PetscSubcomm using the INTERLACED
1305a04a6428SPatrick 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.
13066fc41876SBarry Smith 
1307005d9f20SPatrick Sanan    The telescoping preconditioner is aware of nullspaces and near nullspaces which are attached to the B operator.
13088439623fSPatrick Sanan    In the case where B has a (near) nullspace attached, the (near) nullspace vectors are extracted from B and mapped into
1309005d9f20SPatrick Sanan    a new (near) nullspace, defined on the sub-communicator, which is attached to B' (the B operator which was scattered to c')
13106fc41876SBarry Smith 
131100fea0ebSDave May    The telescoping preconditioner can re-partition an attached DM if it is a DMDA (2D or 3D -
13124c500f23SPierre Jolivet    support for 1D DMDAs is not provided). If a DMDA is found, a topologically equivalent DMDA is created on c'
131300fea0ebSDave May    and this new DM is attached the sub KSP. The design of telescope is such that it should be possible to extend support
13148439623fSPatrick Sanan    for re-partitioning other to DM's (e.g. DMPLEX). The user can supply a flag to ignore attached DMs.
131500fea0ebSDave May    Alternatively, user-provided re-partitioned DMs can be used via -pc_telescope_use_coarse_dm.
13166fc41876SBarry Smith 
131700fea0ebSDave May    With the default setup mode, B' is defined by fusing rows (in order) associated with MPI ranks common to c and c'.
13186fc41876SBarry Smith 
13198439623fSPatrick Sanan    When a DMDA is attached to the parent preconditioner, B' is defined by: (i) performing a symmetric permutation of B
13207dae84e0SHong Zhang    into the ordering defined by the DMDA on c', (ii) extracting the local chunks via MatCreateSubMatrices(), (iii) fusing the
13216fc41876SBarry Smith    locally (sequential) matrices defined on the ranks common to c and c' into B' using MatCreateMPIMatConcatenateSeqMat()
13226fc41876SBarry Smith 
13238439623fSPatrick Sanan    Limitations/improvements include the following.
13248439623fSPatrick Sanan    VecPlaceArray() could be used within PCApply() to improve efficiency and reduce memory usage.
132500fea0ebSDave May    A unified mechanism to query for user contexts as required by KSPSetComputeOperators() and MatNullSpaceSetFunction().
13266fc41876SBarry Smith 
13270705ae88SPierre Jolivet    The symmetric permutation used when a DMDA is encountered is performed via explicitly assembling a permutation matrix P,
13288439623fSPatrick 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
13290705ae88SPierre Jolivet    VecPermute() does not support the use case required here. By computing P, one can permute both the operator and RHS in a
13306fc41876SBarry Smith    consistent manner.
13316fc41876SBarry Smith 
133200fea0ebSDave May    Mapping of vectors (default setup mode) is performed in the following way.
133300fea0ebSDave May    Suppose the parent communicator size was 4, and we set a reduction factor of 2; this would give a comm size on c' of 2.
13348439623fSPatrick Sanan    Using the interlaced creation routine, the ranks in c with color = 0 will be rank 0 and 2.
133500fea0ebSDave May    We perform the scatter to the sub-communicator in the following way.
1336514db83aSDave May    [1] Given a vector x defined on communicator c
13376fc41876SBarry Smith 
1338514db83aSDave May .vb
1339514db83aSDave May    rank(c)  local values of x
1340514db83aSDave May    ------- ----------------------------------------
1341514db83aSDave May         0   [  0.0,  1.0,  2.0,  3.0,  4.0,  5.0 ]
1342514db83aSDave May         1   [  6.0,  7.0,  8.0,  9.0, 10.0, 11.0 ]
1343514db83aSDave May         2   [ 12.0, 13.0, 14.0, 15.0, 16.0, 17.0 ]
1344514db83aSDave May         3   [ 18.0, 19.0, 20.0, 21.0, 22.0, 23.0 ]
1345514db83aSDave May .ve
13466fc41876SBarry Smith 
1347514db83aSDave May    scatter into xtmp defined also on comm c, so that we have the following values
13486fc41876SBarry Smith 
1349514db83aSDave May .vb
1350514db83aSDave May    rank(c)  local values of xtmp
1351514db83aSDave May    ------- ----------------------------------------------------------------------------
1352514db83aSDave May         0   [  0.0,  1.0,  2.0,  3.0,  4.0,  5.0,  6.0,  7.0,  8.0,  9.0, 10.0, 11.0 ]
1353514db83aSDave May         1   [ ]
1354514db83aSDave May         2   [ 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0 ]
1355514db83aSDave May         3   [ ]
1356514db83aSDave May .ve
13576fc41876SBarry Smith 
13586fc41876SBarry Smith    The entries on rank 1 and 3 (ranks which do not have a color = 0 in c') have no values
13596fc41876SBarry Smith 
1360514db83aSDave May    [2] Copy the values from ranks 0, 2 (indices with respect to comm c) into the vector xred which is defined on communicator c'.
13616fc41876SBarry Smith    Ranks 0 and 2 are the only ranks in the subcomm which have a color = 0.
13626fc41876SBarry Smith 
1363514db83aSDave May .vb
1364514db83aSDave May    rank(c')  local values of xred
1365514db83aSDave May    -------- ----------------------------------------------------------------------------
1366514db83aSDave May          0   [  0.0,  1.0,  2.0,  3.0,  4.0,  5.0,  6.0,  7.0,  8.0,  9.0, 10.0, 11.0 ]
1367514db83aSDave May          1   [ 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0 ]
1368514db83aSDave May .ve
13691e07b27eSBarry Smith 
13701e07b27eSBarry Smith   Contributed by Dave May
13711e07b27eSBarry Smith 
1372bf00f589SPatrick Sanan   Reference:
1373bf00f589SPatrick 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
1374bf00f589SPatrick Sanan 
13756fc41876SBarry Smith .seealso:  PCTelescopeGetKSP(), PCTelescopeGetDM(), PCTelescopeGetReductionFactor(), PCTelescopeSetReductionFactor(), PCTelescopeGetIgnoreDM(), PCTelescopeSetIgnoreDM(), PCREDUNDANT
13761e07b27eSBarry Smith M*/
13771e07b27eSBarry Smith PETSC_EXTERN PetscErrorCode PCCreate_Telescope(PC pc)
13781e07b27eSBarry Smith {
13791e07b27eSBarry Smith   PetscErrorCode       ierr;
13801e07b27eSBarry Smith   struct _PC_Telescope *sred;
13811e07b27eSBarry Smith 
13821e07b27eSBarry Smith   PetscFunctionBegin;
13831e07b27eSBarry Smith   ierr = PetscNewLog(pc,&sred);CHKERRQ(ierr);
13842a22aa42SDave May   sred->psubcomm       = NULL;
138548a10b22SPatrick Sanan   sred->subcommtype    = PETSC_SUBCOMM_INTERLACED;
13862a22aa42SDave May   sred->subcomm        = MPI_COMM_NULL;
13871e07b27eSBarry Smith   sred->redfactor      = 1;
13881e07b27eSBarry Smith   sred->ignore_dm      = PETSC_FALSE;
13897c5279cbSDave May   sred->ignore_kspcomputeoperators = PETSC_FALSE;
13908d9f7141SDave May   sred->use_coarse_dm  = PETSC_FALSE;
13911e07b27eSBarry Smith   pc->data             = (void*)sred;
13921e07b27eSBarry Smith 
13931e07b27eSBarry Smith   pc->ops->apply           = PCApply_Telescope;
13941e07b27eSBarry Smith   pc->ops->applytranspose  = NULL;
1395f650675bSDave May   pc->ops->applyrichardson = PCApplyRichardson_Telescope;
13961e07b27eSBarry Smith   pc->ops->setup           = PCSetUp_Telescope;
13971e07b27eSBarry Smith   pc->ops->destroy         = PCDestroy_Telescope;
13981e07b27eSBarry Smith   pc->ops->reset           = PCReset_Telescope;
13991e07b27eSBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_Telescope;
14001e07b27eSBarry Smith   pc->ops->view            = PCView_Telescope;
14011e07b27eSBarry Smith 
14021e07b27eSBarry Smith   sred->pctelescope_setup_type              = PCTelescopeSetUp_default;
14031e07b27eSBarry Smith   sred->pctelescope_matcreate_type          = PCTelescopeMatCreate_default;
14041e07b27eSBarry Smith   sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_default;
14051e07b27eSBarry Smith   sred->pctelescope_reset_type              = NULL;
14061e07b27eSBarry Smith 
14071e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetKSP_C",PCTelescopeGetKSP_Telescope);CHKERRQ(ierr);
140848a10b22SPatrick Sanan   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetSubcommType_C",PCTelescopeGetSubcommType_Telescope);CHKERRQ(ierr);
140948a10b22SPatrick Sanan   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetSubcommType_C",PCTelescopeSetSubcommType_Telescope);CHKERRQ(ierr);
14101e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetReductionFactor_C",PCTelescopeGetReductionFactor_Telescope);CHKERRQ(ierr);
14111e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetReductionFactor_C",PCTelescopeSetReductionFactor_Telescope);CHKERRQ(ierr);
14121e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetIgnoreDM_C",PCTelescopeGetIgnoreDM_Telescope);CHKERRQ(ierr);
14131e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetIgnoreDM_C",PCTelescopeSetIgnoreDM_Telescope);CHKERRQ(ierr);
14140ae7c45bSDave May   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetIgnoreKSPComputeOperators_C",PCTelescopeGetIgnoreKSPComputeOperators_Telescope);CHKERRQ(ierr);
14150ae7c45bSDave May   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetIgnoreKSPComputeOperators_C",PCTelescopeSetIgnoreKSPComputeOperators_Telescope);CHKERRQ(ierr);
14161e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetDM_C",PCTelescopeGetDM_Telescope);CHKERRQ(ierr);
14178d9f7141SDave May   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetUseCoarseDM_C",PCTelescopeGetUseCoarseDM_Telescope);CHKERRQ(ierr);
14188d9f7141SDave May   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetUseCoarseDM_C",PCTelescopeSetUseCoarseDM_Telescope);CHKERRQ(ierr);
14191e07b27eSBarry Smith   PetscFunctionReturn(0);
14201e07b27eSBarry Smith }
1421