xref: /petsc/src/ksp/pc/impls/telescope/telescope.c (revision 1baa6e3354bfe224b33a0c158f482508792a8a6e)
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   PetscMPIInt    count,k,size_f = 0,size_c = 0,size_c_sum = 0;
575bd1e576SStefano Zampini   PetscMPIInt    *ranks_f,*ranks_c;
588d9f7141SDave May 
5957f12427SDave May   PetscFunctionBegin;
6008401ef6SPierre Jolivet   PetscCheck(comm_f != MPI_COMM_NULL,PETSC_COMM_SELF,PETSC_ERR_SUP,"comm_f cannot be MPI_COMM_NULL");
618d9f7141SDave May 
629566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_group(comm_f,&group_f));
638d9f7141SDave May   if (comm_c != MPI_COMM_NULL) {
649566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_group(comm_c,&group_c));
658d9f7141SDave May   }
668d9f7141SDave May 
679566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm_f,&size_f));
688d9f7141SDave May   if (comm_c != MPI_COMM_NULL) {
699566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm_c,&size_c));
708d9f7141SDave May   }
718d9f7141SDave May 
728d9f7141SDave May   /* check not all comm_c's are NULL */
738d9f7141SDave May   size_c_sum = size_c;
749566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE,&size_c_sum,1,MPI_INT,MPI_SUM,comm_f));
755bd1e576SStefano Zampini   if (size_c_sum == 0) valid = 0;
768d9f7141SDave May 
778d9f7141SDave May   /* check we can map at least 1 rank in comm_c to comm_f */
789566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size_f,&ranks_f));
799566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size_c,&ranks_c));
805bd1e576SStefano Zampini   for (k=0; k<size_f; k++) ranks_f[k] = MPI_UNDEFINED;
815bd1e576SStefano Zampini   for (k=0; k<size_c; k++) ranks_c[k] = k;
828d9f7141SDave May 
8357f12427SDave May   /*
8457f12427SDave May    MPI_Group_translate_ranks() returns a non-zero exit code if any rank cannot be translated.
8557f12427SDave May    I do not want the code to terminate immediately if this occurs, rather I want to throw
8657f12427SDave May    the error later (during PCSetUp_Telescope()) via SETERRQ() with a message indicating
8757f12427SDave May    that comm_c is not a valid sub-communicator.
889566063dSJacob Faibussowitsch    Hence I purposefully do not call PetscCall() after MPI_Group_translate_ranks().
8957f12427SDave May   */
908d9f7141SDave May   count = 0;
918d9f7141SDave May   if (comm_c != MPI_COMM_NULL) {
9266b79024SDave May     (void)MPI_Group_translate_ranks(group_c,size_c,ranks_c,group_f,ranks_f);
938d9f7141SDave May     for (k=0; k<size_f; k++) {
948d9f7141SDave May       if (ranks_f[k] == MPI_UNDEFINED) {
958d9f7141SDave May         count++;
968d9f7141SDave May       }
978d9f7141SDave May     }
988d9f7141SDave May   }
995bd1e576SStefano Zampini   if (count == size_f) valid = 0;
1008d9f7141SDave May 
1019566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE,&valid,1,MPIU_INT,MPI_MIN,comm_f));
1025bd1e576SStefano Zampini   if (valid == 1) *isvalid = PETSC_TRUE;
1035bd1e576SStefano Zampini   else *isvalid = PETSC_FALSE;
1048d9f7141SDave May 
1059566063dSJacob Faibussowitsch   PetscCall(PetscFree(ranks_f));
1069566063dSJacob Faibussowitsch   PetscCall(PetscFree(ranks_c));
1079566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Group_free(&group_f));
1088d9f7141SDave May   if (comm_c != MPI_COMM_NULL) {
1099566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Group_free(&group_c));
1108d9f7141SDave May   }
1118d9f7141SDave May   PetscFunctionReturn(0);
1128d9f7141SDave May }
1138d9f7141SDave May 
1141e07b27eSBarry Smith DM private_PCTelescopeGetSubDM(PC_Telescope sred)
1151e07b27eSBarry Smith {
116c6a0d831SBarry Smith   DM subdm = NULL;
1171e07b27eSBarry Smith 
11857f12427SDave May   if (!PCTelescope_isActiveRank(sred)) { subdm = NULL; }
1191e07b27eSBarry Smith   else {
1201e07b27eSBarry Smith     switch (sred->sr_type) {
1211e07b27eSBarry Smith     case TELESCOPE_DEFAULT: subdm = NULL;
1221e07b27eSBarry Smith       break;
1231e07b27eSBarry Smith     case TELESCOPE_DMDA:    subdm = ((PC_Telescope_DMDACtx*)sred->dm_ctx)->dmrepart;
1241e07b27eSBarry Smith       break;
1251e07b27eSBarry Smith     case TELESCOPE_DMPLEX:  subdm = NULL;
1261e07b27eSBarry Smith       break;
1278d9f7141SDave May     case TELESCOPE_COARSEDM: if (sred->ksp) { KSPGetDM(sred->ksp,&subdm); }
1288d9f7141SDave May       break;
1291e07b27eSBarry Smith     }
1301e07b27eSBarry Smith   }
1311e07b27eSBarry Smith   return(subdm);
1321e07b27eSBarry Smith }
1331e07b27eSBarry Smith 
1341e07b27eSBarry Smith PetscErrorCode PCTelescopeSetUp_default(PC pc,PC_Telescope sred)
1351e07b27eSBarry Smith {
1361e07b27eSBarry Smith   PetscInt       m,M,bs,st,ed;
1371e07b27eSBarry Smith   Vec            x,xred,yred,xtmp;
1381e07b27eSBarry Smith   Mat            B;
1391e07b27eSBarry Smith   MPI_Comm       comm,subcomm;
1401e07b27eSBarry Smith   VecScatter     scatter;
1411e07b27eSBarry Smith   IS             isin;
14254cd43dcSJunchao Zhang   VecType        vectype;
1431e07b27eSBarry Smith 
1441e07b27eSBarry Smith   PetscFunctionBegin;
1459566063dSJacob Faibussowitsch   PetscCall(PetscInfo(pc,"PCTelescope: setup (default)\n"));
1461e07b27eSBarry Smith   comm = PetscSubcommParent(sred->psubcomm);
1471e07b27eSBarry Smith   subcomm = PetscSubcommChild(sred->psubcomm);
1481e07b27eSBarry Smith 
1499566063dSJacob Faibussowitsch   PetscCall(PCGetOperators(pc,NULL,&B));
1509566063dSJacob Faibussowitsch   PetscCall(MatGetSize(B,&M,NULL));
1519566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(B,&bs));
1529566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(B,&x,NULL));
1539566063dSJacob Faibussowitsch   PetscCall(MatGetVecType(B,&vectype));
1541e07b27eSBarry Smith 
1551e07b27eSBarry Smith   xred = NULL;
1563ac26c5eSBarry Smith   m    = 0;
15757f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
1589566063dSJacob Faibussowitsch     PetscCall(VecCreate(subcomm,&xred));
1599566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(xred,PETSC_DECIDE,M));
1609566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(xred,bs));
1619566063dSJacob Faibussowitsch     PetscCall(VecSetType(xred,vectype)); /* Use the preconditioner matrix's vectype by default */
1629566063dSJacob Faibussowitsch     PetscCall(VecSetFromOptions(xred));
1639566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(xred,&m));
1641e07b27eSBarry Smith   }
1651e07b27eSBarry Smith 
1661e07b27eSBarry Smith   yred = NULL;
16757f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
1689566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(xred,&yred));
1691e07b27eSBarry Smith   }
1701e07b27eSBarry Smith 
1719566063dSJacob Faibussowitsch   PetscCall(VecCreate(comm,&xtmp));
1729566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(xtmp,m,PETSC_DECIDE));
1739566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(xtmp,bs));
1749566063dSJacob Faibussowitsch   PetscCall(VecSetType(xtmp,vectype));
1751e07b27eSBarry Smith 
17657f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
1779566063dSJacob Faibussowitsch     PetscCall(VecGetOwnershipRange(xred,&st,&ed));
1789566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(comm,(ed-st),st,1,&isin));
1791e07b27eSBarry Smith   } else {
1809566063dSJacob Faibussowitsch     PetscCall(VecGetOwnershipRange(x,&st,&ed));
1819566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(comm,0,st,1,&isin));
1821e07b27eSBarry Smith   }
1839566063dSJacob Faibussowitsch   PetscCall(ISSetBlockSize(isin,bs));
1841e07b27eSBarry Smith 
1859566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(x,isin,xtmp,NULL,&scatter));
1861e07b27eSBarry Smith 
1871e07b27eSBarry Smith   sred->isin    = isin;
1881e07b27eSBarry Smith   sred->scatter = scatter;
1891e07b27eSBarry Smith   sred->xred    = xred;
1901e07b27eSBarry Smith   sred->yred    = yred;
1911e07b27eSBarry Smith   sred->xtmp    = xtmp;
1929566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&x));
1931e07b27eSBarry Smith   PetscFunctionReturn(0);
1941e07b27eSBarry Smith }
1951e07b27eSBarry Smith 
1961e07b27eSBarry Smith PetscErrorCode PCTelescopeMatCreate_default(PC pc,PC_Telescope sred,MatReuse reuse,Mat *A)
1971e07b27eSBarry Smith {
1981e07b27eSBarry Smith   MPI_Comm       comm,subcomm;
1991e07b27eSBarry Smith   Mat            Bred,B;
2005624f943SPierre Jolivet   PetscInt       nr,nc,bs;
2011e07b27eSBarry Smith   IS             isrow,iscol;
2021e07b27eSBarry Smith   Mat            Blocal,*_Blocal;
2031e07b27eSBarry Smith 
2041e07b27eSBarry Smith   PetscFunctionBegin;
2059566063dSJacob Faibussowitsch   PetscCall(PetscInfo(pc,"PCTelescope: updating the redundant preconditioned operator (default)\n"));
2069566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)pc,&comm));
2071e07b27eSBarry Smith   subcomm = PetscSubcommChild(sred->psubcomm);
2089566063dSJacob Faibussowitsch   PetscCall(PCGetOperators(pc,NULL,&B));
2099566063dSJacob Faibussowitsch   PetscCall(MatGetSize(B,&nr,&nc));
2101e07b27eSBarry Smith   isrow = sred->isin;
2119566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF,nc,0,1,&iscol));
2129566063dSJacob Faibussowitsch   PetscCall(ISSetIdentity(iscol));
2139566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSizes(B,NULL,&bs));
2149566063dSJacob Faibussowitsch   PetscCall(ISSetBlockSize(iscol,bs));
2159566063dSJacob Faibussowitsch   PetscCall(MatSetOption(B,MAT_SUBMAT_SINGLEIS,PETSC_TRUE));
2169566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrices(B,1,&isrow,&iscol,MAT_INITIAL_MATRIX,&_Blocal));
2171e07b27eSBarry Smith   Blocal = *_Blocal;
2189566063dSJacob Faibussowitsch   PetscCall(PetscFree(_Blocal));
2191e07b27eSBarry Smith   Bred = NULL;
22057f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
2211e07b27eSBarry Smith     PetscInt mm;
2221e07b27eSBarry Smith 
2231e07b27eSBarry Smith     if (reuse != MAT_INITIAL_MATRIX) { Bred = *A; }
2241e07b27eSBarry Smith 
2259566063dSJacob Faibussowitsch     PetscCall(MatGetSize(Blocal,&mm,NULL));
2269566063dSJacob Faibussowitsch     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm,Blocal,mm,reuse,&Bred));
2271e07b27eSBarry Smith   }
2281e07b27eSBarry Smith   *A = Bred;
2299566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&iscol));
2309566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&Blocal));
2311e07b27eSBarry Smith   PetscFunctionReturn(0);
2321e07b27eSBarry Smith }
2331e07b27eSBarry Smith 
234392968a1SPatrick Sanan static PetscErrorCode PCTelescopeSubNullSpaceCreate_Telescope(PC pc,PC_Telescope sred,MatNullSpace nullspace,MatNullSpace *sub_nullspace)
2351e07b27eSBarry Smith {
2361e07b27eSBarry Smith   PetscBool      has_const;
2371e07b27eSBarry Smith   const Vec      *vecs;
238c41e779fSDave May   Vec            *sub_vecs = NULL;
239392968a1SPatrick Sanan   PetscInt       i,k,n = 0;
2401e07b27eSBarry Smith   MPI_Comm       subcomm;
2411e07b27eSBarry Smith 
2421e07b27eSBarry Smith   PetscFunctionBegin;
2431e07b27eSBarry Smith   subcomm = PetscSubcommChild(sred->psubcomm);
2449566063dSJacob Faibussowitsch   PetscCall(MatNullSpaceGetVecs(nullspace,&has_const,&n,&vecs));
2451e07b27eSBarry Smith 
24657f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
247e3acf2f7SBarry Smith     if (n) {
2489566063dSJacob Faibussowitsch       PetscCall(VecDuplicateVecs(sred->xred,n,&sub_vecs));
2491e07b27eSBarry Smith     }
2501e07b27eSBarry Smith   }
2511e07b27eSBarry Smith 
2521e07b27eSBarry Smith   /* copy entries */
2531e07b27eSBarry Smith   for (k=0; k<n; k++) {
2541e07b27eSBarry Smith     const PetscScalar *x_array;
2551e07b27eSBarry Smith     PetscScalar       *LA_sub_vec;
25613c30530SDave May     PetscInt          st,ed;
2571e07b27eSBarry Smith 
2581e07b27eSBarry Smith     /* pull in vector x->xtmp */
2599566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(sred->scatter,vecs[k],sred->xtmp,INSERT_VALUES,SCATTER_FORWARD));
2609566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(sred->scatter,vecs[k],sred->xtmp,INSERT_VALUES,SCATTER_FORWARD));
26147856c66SBarry Smith     if (sub_vecs) {
262a04a6428SPatrick Sanan       /* copy vector entries into xred */
2639566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(sred->xtmp,&x_array));
264ea2b237eSDave May       if (sub_vecs[k]) {
2659566063dSJacob Faibussowitsch         PetscCall(VecGetOwnershipRange(sub_vecs[k],&st,&ed));
2669566063dSJacob Faibussowitsch         PetscCall(VecGetArray(sub_vecs[k],&LA_sub_vec));
2671e07b27eSBarry Smith         for (i=0; i<ed-st; i++) {
2681e07b27eSBarry Smith           LA_sub_vec[i] = x_array[i];
2691e07b27eSBarry Smith         }
2709566063dSJacob Faibussowitsch         PetscCall(VecRestoreArray(sub_vecs[k],&LA_sub_vec));
2711e07b27eSBarry Smith       }
2729566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(sred->xtmp,&x_array));
2731e07b27eSBarry Smith     }
27447856c66SBarry Smith   }
2751e07b27eSBarry Smith 
27657f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
277d8b9d5b7SPatrick Sanan     /* create new (near) nullspace for redundant object */
2789566063dSJacob Faibussowitsch     PetscCall(MatNullSpaceCreate(subcomm,has_const,n,sub_vecs,sub_nullspace));
2799566063dSJacob Faibussowitsch     PetscCall(VecDestroyVecs(n,&sub_vecs));
28028b400f6SJacob Faibussowitsch     PetscCheck(!nullspace->remove,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Propagation of custom remove callbacks not supported when propagating (near) nullspaces with PCTelescope");
28128b400f6SJacob Faibussowitsch     PetscCheck(!nullspace->rmctx,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Propagation of custom remove callback context not supported when propagating (near) nullspaces with PCTelescope");
282d8b9d5b7SPatrick Sanan   }
283392968a1SPatrick Sanan   PetscFunctionReturn(0);
284392968a1SPatrick Sanan }
285392968a1SPatrick Sanan 
286392968a1SPatrick Sanan static PetscErrorCode PCTelescopeMatNullSpaceCreate_default(PC pc,PC_Telescope sred,Mat sub_mat)
287392968a1SPatrick Sanan {
288392968a1SPatrick Sanan   Mat            B;
289392968a1SPatrick Sanan 
290392968a1SPatrick Sanan   PetscFunctionBegin;
2919566063dSJacob Faibussowitsch   PetscCall(PCGetOperators(pc,NULL,&B));
292392968a1SPatrick Sanan   /* Propagate the nullspace if it exists */
293392968a1SPatrick Sanan   {
294392968a1SPatrick Sanan     MatNullSpace nullspace,sub_nullspace;
2959566063dSJacob Faibussowitsch     PetscCall(MatGetNullSpace(B,&nullspace));
296392968a1SPatrick Sanan     if (nullspace) {
2979566063dSJacob Faibussowitsch       PetscCall(PetscInfo(pc,"PCTelescope: generating nullspace (default)\n"));
2989566063dSJacob Faibussowitsch       PetscCall(PCTelescopeSubNullSpaceCreate_Telescope(pc,sred,nullspace,&sub_nullspace));
29957f12427SDave May       if (PCTelescope_isActiveRank(sred)) {
3009566063dSJacob Faibussowitsch         PetscCall(MatSetNullSpace(sub_mat,sub_nullspace));
3019566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceDestroy(&sub_nullspace));
3021e07b27eSBarry Smith       }
303392968a1SPatrick Sanan     }
304392968a1SPatrick Sanan   }
305392968a1SPatrick Sanan   /* Propagate the near nullspace if it exists */
306392968a1SPatrick Sanan   {
307392968a1SPatrick Sanan     MatNullSpace nearnullspace,sub_nearnullspace;
3089566063dSJacob Faibussowitsch     PetscCall(MatGetNearNullSpace(B,&nearnullspace));
309392968a1SPatrick Sanan     if (nearnullspace) {
3109566063dSJacob Faibussowitsch       PetscCall(PetscInfo(pc,"PCTelescope: generating near nullspace (default)\n"));
3119566063dSJacob Faibussowitsch       PetscCall(PCTelescopeSubNullSpaceCreate_Telescope(pc,sred,nearnullspace,&sub_nearnullspace));
31257f12427SDave May       if (PCTelescope_isActiveRank(sred)) {
3139566063dSJacob Faibussowitsch         PetscCall(MatSetNearNullSpace(sub_mat,sub_nearnullspace));
3149566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceDestroy(&sub_nearnullspace));
315392968a1SPatrick Sanan       }
316392968a1SPatrick Sanan     }
317392968a1SPatrick Sanan   }
3181e07b27eSBarry Smith   PetscFunctionReturn(0);
3191e07b27eSBarry Smith }
3201e07b27eSBarry Smith 
3211e07b27eSBarry Smith static PetscErrorCode PCView_Telescope(PC pc,PetscViewer viewer)
3221e07b27eSBarry Smith {
3231e07b27eSBarry Smith   PC_Telescope   sred = (PC_Telescope)pc->data;
3241e07b27eSBarry Smith   PetscBool      iascii,isstring;
3251e07b27eSBarry Smith   PetscViewer    subviewer;
3261e07b27eSBarry Smith 
3271e07b27eSBarry Smith   PetscFunctionBegin;
3289566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
3299566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring));
3301e07b27eSBarry Smith   if (iascii) {
3318d9f7141SDave May     {
3321e07b27eSBarry Smith       MPI_Comm    comm,subcomm;
3331e07b27eSBarry Smith       PetscMPIInt comm_size,subcomm_size;
3348d9f7141SDave May       DM          dm = NULL,subdm = NULL;
3351e07b27eSBarry Smith 
3369566063dSJacob Faibussowitsch       PetscCall(PCGetDM(pc,&dm));
3371e07b27eSBarry Smith       subdm = private_PCTelescopeGetSubDM(sred);
3388d9f7141SDave May 
3398d9f7141SDave May       if (sred->psubcomm) {
3401e07b27eSBarry Smith         comm = PetscSubcommParent(sred->psubcomm);
3411e07b27eSBarry Smith         subcomm = PetscSubcommChild(sred->psubcomm);
3429566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Comm_size(comm,&comm_size));
3439566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Comm_size(subcomm,&subcomm_size));
3441e07b27eSBarry Smith 
3459566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
34663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer,"petsc subcomm: parent comm size reduction factor = %" PetscInt_FMT "\n",sred->redfactor));
3479566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer,"petsc subcomm: parent_size = %d , subcomm_size = %d\n",(int)comm_size,(int)subcomm_size));
34848a10b22SPatrick Sanan         switch (sred->subcommtype) {
34948a10b22SPatrick Sanan         case PETSC_SUBCOMM_INTERLACED :
35063a3b9bcSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer,"petsc subcomm: type = %s\n",PetscSubcommTypes[sred->subcommtype]));
35148a10b22SPatrick Sanan           break;
35248a10b22SPatrick Sanan         case PETSC_SUBCOMM_CONTIGUOUS :
35363a3b9bcSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer,"petsc subcomm type = %s\n",PetscSubcommTypes[sred->subcommtype]));
35448a10b22SPatrick Sanan           break;
35548a10b22SPatrick Sanan         default :
35648a10b22SPatrick Sanan           SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"General subcomm type not supported by PCTelescope");
35748a10b22SPatrick Sanan         }
3589566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
3598d9f7141SDave May       } else {
3609566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetComm((PetscObject)pc,&comm));
3618d9f7141SDave May         subcomm = sred->subcomm;
36257f12427SDave May         if (!PCTelescope_isActiveRank(sred)) {
3638d9f7141SDave May           subcomm = PETSC_COMM_SELF;
3648d9f7141SDave May         }
3658d9f7141SDave May 
3669566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
3679566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer,"subcomm: using user provided sub-communicator\n"));
3689566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
3698d9f7141SDave May       }
3708d9f7141SDave May 
3719566063dSJacob Faibussowitsch       PetscCall(PetscViewerGetSubViewer(viewer,subcomm,&subviewer));
37257f12427SDave May       if (PCTelescope_isActiveRank(sred)) {
3739566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(subviewer));
3741e07b27eSBarry Smith 
3751e07b27eSBarry Smith         if (dm && sred->ignore_dm) {
3769566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(subviewer,"ignoring DM\n"));
3771e07b27eSBarry Smith         }
3787c5279cbSDave May         if (sred->ignore_kspcomputeoperators) {
3799566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(subviewer,"ignoring KSPComputeOperators\n"));
3807c5279cbSDave May         }
3811e07b27eSBarry Smith         switch (sred->sr_type) {
3821e07b27eSBarry Smith         case TELESCOPE_DEFAULT:
3839566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(subviewer,"setup type: default\n"));
3841e07b27eSBarry Smith           break;
3851e07b27eSBarry Smith         case TELESCOPE_DMDA:
3869566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(subviewer,"setup type: DMDA auto-repartitioning\n"));
3879566063dSJacob Faibussowitsch           PetscCall(DMView_DA_Short(subdm,subviewer));
3881e07b27eSBarry Smith           break;
3891e07b27eSBarry Smith         case TELESCOPE_DMPLEX:
3909566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(subviewer,"setup type: DMPLEX auto-repartitioning\n"));
3911e07b27eSBarry Smith           break;
3928d9f7141SDave May         case TELESCOPE_COARSEDM:
3939566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(subviewer,"setup type: coarse DM\n"));
3948d9f7141SDave May           break;
3958d9f7141SDave May         }
3968d9f7141SDave May 
3978d9f7141SDave May         if (dm) {
3988d9f7141SDave May           PetscObject obj = (PetscObject)dm;
3999566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(subviewer,"Parent DM object:"));
4008d9f7141SDave May           PetscViewerASCIIUseTabs(subviewer,PETSC_FALSE);
4018d9f7141SDave May           if (obj->type_name) { PetscViewerASCIIPrintf(subviewer," type = %s;",obj->type_name); }
4028d9f7141SDave May           if (obj->name) { PetscViewerASCIIPrintf(subviewer," name = %s;",obj->name); }
4038d9f7141SDave May           if (obj->prefix) { PetscViewerASCIIPrintf(subviewer," prefix = %s",obj->prefix); }
4049566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(subviewer,"\n"));
4058d9f7141SDave May           PetscViewerASCIIUseTabs(subviewer,PETSC_TRUE);
4068d9f7141SDave May         } else {
4079566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(subviewer,"Parent DM object: NULL\n"));
4088d9f7141SDave May         }
4098d9f7141SDave May         if (subdm) {
4108d9f7141SDave May           PetscObject obj = (PetscObject)subdm;
4119566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(subviewer,"Sub DM object:"));
4128d9f7141SDave May           PetscViewerASCIIUseTabs(subviewer,PETSC_FALSE);
4138d9f7141SDave May           if (obj->type_name) { PetscViewerASCIIPrintf(subviewer," type = %s;",obj->type_name); }
4148d9f7141SDave May           if (obj->name) { PetscViewerASCIIPrintf(subviewer," name = %s;",obj->name); }
4158d9f7141SDave May           if (obj->prefix) { PetscViewerASCIIPrintf(subviewer," prefix = %s",obj->prefix); }
4169566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(subviewer,"\n"));
4178d9f7141SDave May           PetscViewerASCIIUseTabs(subviewer,PETSC_TRUE);
4188d9f7141SDave May         } else {
4199566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(subviewer,"Sub DM object: NULL\n"));
4201e07b27eSBarry Smith         }
4211e07b27eSBarry Smith 
4229566063dSJacob Faibussowitsch         PetscCall(KSPView(sred->ksp,subviewer));
4239566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(subviewer));
4241e07b27eSBarry Smith       }
4259566063dSJacob Faibussowitsch       PetscCall(PetscViewerRestoreSubViewer(viewer,subcomm,&subviewer));
4261e07b27eSBarry Smith     }
4271e07b27eSBarry Smith   }
4281e07b27eSBarry Smith   PetscFunctionReturn(0);
4291e07b27eSBarry Smith }
4301e07b27eSBarry Smith 
4311e07b27eSBarry Smith static PetscErrorCode PCSetUp_Telescope(PC pc)
4321e07b27eSBarry Smith {
4331e07b27eSBarry Smith   PC_Telescope    sred = (PC_Telescope)pc->data;
434bd49479cSSatish Balay   MPI_Comm        comm,subcomm=0;
4351e07b27eSBarry Smith   PCTelescopeType sr_type;
4361e07b27eSBarry Smith 
4371e07b27eSBarry Smith   PetscFunctionBegin;
4389566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)pc,&comm));
4391e07b27eSBarry Smith 
4401e07b27eSBarry Smith   /* Determine type of setup/update */
4411e07b27eSBarry Smith   if (!pc->setupcalled) {
4421e07b27eSBarry Smith     PetscBool has_dm,same;
4431e07b27eSBarry Smith     DM        dm;
4441e07b27eSBarry Smith 
4451e07b27eSBarry Smith     sr_type = TELESCOPE_DEFAULT;
4461e07b27eSBarry Smith     has_dm = PETSC_FALSE;
4479566063dSJacob Faibussowitsch     PetscCall(PCGetDM(pc,&dm));
4481e07b27eSBarry Smith     if (dm) { has_dm = PETSC_TRUE; }
4491e07b27eSBarry Smith     if (has_dm) {
4501e07b27eSBarry Smith       /* check for dmda */
4519566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)dm,DMDA,&same));
4521e07b27eSBarry Smith       if (same) {
4539566063dSJacob Faibussowitsch         PetscCall(PetscInfo(pc,"PCTelescope: found DMDA\n"));
4541e07b27eSBarry Smith         sr_type = TELESCOPE_DMDA;
4551e07b27eSBarry Smith       }
4561e07b27eSBarry Smith       /* check for dmplex */
4579566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&same));
4581e07b27eSBarry Smith       if (same) {
4599566063dSJacob Faibussowitsch         PetscCall(PetscInfo(pc,"PCTelescope: found DMPLEX\n"));
4601e07b27eSBarry Smith         sr_type = TELESCOPE_DMPLEX;
4611e07b27eSBarry Smith       }
4628d9f7141SDave May 
4638d9f7141SDave May       if (sred->use_coarse_dm) {
4649566063dSJacob Faibussowitsch         PetscCall(PetscInfo(pc,"PCTelescope: using coarse DM\n"));
4658d9f7141SDave May         sr_type = TELESCOPE_COARSEDM;
4661e07b27eSBarry Smith       }
4671e07b27eSBarry Smith 
4681e07b27eSBarry Smith       if (sred->ignore_dm) {
4699566063dSJacob Faibussowitsch         PetscCall(PetscInfo(pc,"PCTelescope: ignoring DM\n"));
4701e07b27eSBarry Smith         sr_type = TELESCOPE_DEFAULT;
4711e07b27eSBarry Smith       }
4728d9f7141SDave May     }
4731e07b27eSBarry Smith     sred->sr_type = sr_type;
4741e07b27eSBarry Smith   } else {
4751e07b27eSBarry Smith     sr_type = sred->sr_type;
4761e07b27eSBarry Smith   }
4771e07b27eSBarry Smith 
478d8b9d5b7SPatrick Sanan   /* set function pointers for repartition setup, matrix creation/update, matrix (near) nullspace, and reset functionality */
4791e07b27eSBarry Smith   switch (sr_type) {
4801e07b27eSBarry Smith   case TELESCOPE_DEFAULT:
4811e07b27eSBarry Smith     sred->pctelescope_setup_type              = PCTelescopeSetUp_default;
4821e07b27eSBarry Smith     sred->pctelescope_matcreate_type          = PCTelescopeMatCreate_default;
4831e07b27eSBarry Smith     sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_default;
4841e07b27eSBarry Smith     sred->pctelescope_reset_type              = NULL;
4851e07b27eSBarry Smith     break;
4861e07b27eSBarry Smith   case TELESCOPE_DMDA:
4871e07b27eSBarry Smith     pc->ops->apply                            = PCApply_Telescope_dmda;
488f650675bSDave May     pc->ops->applyrichardson                  = PCApplyRichardson_Telescope_dmda;
4891e07b27eSBarry Smith     sred->pctelescope_setup_type              = PCTelescopeSetUp_dmda;
4901e07b27eSBarry Smith     sred->pctelescope_matcreate_type          = PCTelescopeMatCreate_dmda;
4911e07b27eSBarry Smith     sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_dmda;
4921e07b27eSBarry Smith     sred->pctelescope_reset_type              = PCReset_Telescope_dmda;
4931e07b27eSBarry Smith     break;
494b458e8f1SJose E. Roman   case TELESCOPE_DMPLEX:
495b458e8f1SJose E. Roman     SETERRQ(comm,PETSC_ERR_SUP,"Support for DMPLEX is currently not available");
4968d9f7141SDave May   case TELESCOPE_COARSEDM:
4978d9f7141SDave May     pc->ops->apply                            = PCApply_Telescope_CoarseDM;
4988d9f7141SDave May     pc->ops->applyrichardson                  = PCApplyRichardson_Telescope_CoarseDM;
4998d9f7141SDave May     sred->pctelescope_setup_type              = PCTelescopeSetUp_CoarseDM;
5008d9f7141SDave May     sred->pctelescope_matcreate_type          = NULL;
5018d9f7141SDave May     sred->pctelescope_matnullspacecreate_type = NULL; /* PCTelescopeMatNullSpaceCreate_CoarseDM; */
5028d9f7141SDave May     sred->pctelescope_reset_type              = PCReset_Telescope_CoarseDM;
5031e07b27eSBarry Smith     break;
504b458e8f1SJose E. Roman   default:
505b458e8f1SJose E. Roman     SETERRQ(comm,PETSC_ERR_SUP,"Support only provided for: repartitioning an operator; repartitioning a DMDA; or using a coarse DM");
5068d9f7141SDave May   }
5078d9f7141SDave May 
5088d9f7141SDave May   /* subcomm definition */
5098d9f7141SDave May   if (!pc->setupcalled) {
5108d9f7141SDave May     if ((sr_type == TELESCOPE_DEFAULT) || (sr_type == TELESCOPE_DMDA)) {
5118d9f7141SDave May       if (!sred->psubcomm) {
5129566063dSJacob Faibussowitsch         PetscCall(PetscSubcommCreate(comm,&sred->psubcomm));
5139566063dSJacob Faibussowitsch         PetscCall(PetscSubcommSetNumber(sred->psubcomm,sred->redfactor));
5149566063dSJacob Faibussowitsch         PetscCall(PetscSubcommSetType(sred->psubcomm,sred->subcommtype));
5159566063dSJacob Faibussowitsch         PetscCall(PetscLogObjectMemory((PetscObject)pc,sizeof(PetscSubcomm)));
5168d9f7141SDave May         sred->subcomm = PetscSubcommChild(sred->psubcomm);
5178d9f7141SDave May       }
5188d9f7141SDave May     } else { /* query PC for DM, check communicators */
5198d9f7141SDave May       DM          dm,dm_coarse_partition = NULL;
5208d9f7141SDave May       MPI_Comm    comm_fine,comm_coarse_partition = MPI_COMM_NULL;
5218d9f7141SDave May       PetscMPIInt csize_fine=0,csize_coarse_partition=0,cs[2],csg[2],cnt=0;
5228d9f7141SDave May       PetscBool   isvalidsubcomm;
5238d9f7141SDave May 
5249566063dSJacob Faibussowitsch       PetscCall(PCGetDM(pc,&dm));
5258d9f7141SDave May       comm_fine = PetscObjectComm((PetscObject)dm);
5269566063dSJacob Faibussowitsch       PetscCall(DMGetCoarseDM(dm,&dm_coarse_partition));
5278d9f7141SDave May       if (dm_coarse_partition) { cnt = 1; }
5289566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE,&cnt,1,MPI_INT,MPI_SUM,comm_fine));
52908401ef6SPierre Jolivet       PetscCheck(cnt != 0,comm_fine,PETSC_ERR_SUP,"Zero instances of a coarse DM were found");
5308d9f7141SDave May 
5319566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_size(comm_fine,&csize_fine));
5328d9f7141SDave May       if (dm_coarse_partition) {
5338d9f7141SDave May         comm_coarse_partition = PetscObjectComm((PetscObject)dm_coarse_partition);
5349566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Comm_size(comm_coarse_partition,&csize_coarse_partition));
5358d9f7141SDave May       }
5368d9f7141SDave May 
5378d9f7141SDave May       cs[0] = csize_fine;
5388d9f7141SDave May       cs[1] = csize_coarse_partition;
5399566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Allreduce(cs,csg,2,MPI_INT,MPI_MAX,comm_fine));
54008401ef6SPierre Jolivet       PetscCheck(csg[0] != csg[1],comm_fine,PETSC_ERR_SUP,"Coarse DM uses the same size communicator as the parent DM attached to the PC");
5418d9f7141SDave May 
5429566063dSJacob Faibussowitsch       PetscCall(PCTelescopeTestValidSubcomm(comm_fine,comm_coarse_partition,&isvalidsubcomm));
54328b400f6SJacob Faibussowitsch       PetscCheck(isvalidsubcomm,comm_fine,PETSC_ERR_SUP,"Coarse DM communicator is not a sub-communicator of parentDM->comm");
5448d9f7141SDave May       sred->subcomm = comm_coarse_partition;
5458d9f7141SDave May     }
5468d9f7141SDave May   }
5478d9f7141SDave May   subcomm = sred->subcomm;
5488d9f7141SDave May 
5498d9f7141SDave May   /* internal KSP */
5508d9f7141SDave May   if (!pc->setupcalled) {
5518d9f7141SDave May     const char *prefix;
5528d9f7141SDave May 
55357f12427SDave May     if (PCTelescope_isActiveRank(sred)) {
5549566063dSJacob Faibussowitsch       PetscCall(KSPCreate(subcomm,&sred->ksp));
5559566063dSJacob Faibussowitsch       PetscCall(KSPSetErrorIfNotConverged(sred->ksp,pc->erroriffailure));
5569566063dSJacob Faibussowitsch       PetscCall(PetscObjectIncrementTabLevel((PetscObject)sred->ksp,(PetscObject)pc,1));
5579566063dSJacob Faibussowitsch       PetscCall(PetscLogObjectParent((PetscObject)pc,(PetscObject)sred->ksp));
5589566063dSJacob Faibussowitsch       PetscCall(KSPSetType(sred->ksp,KSPPREONLY));
5599566063dSJacob Faibussowitsch       PetscCall(PCGetOptionsPrefix(pc,&prefix));
5609566063dSJacob Faibussowitsch       PetscCall(KSPSetOptionsPrefix(sred->ksp,prefix));
5619566063dSJacob Faibussowitsch       PetscCall(KSPAppendOptionsPrefix(sred->ksp,"telescope_"));
5628d9f7141SDave May     }
5631e07b27eSBarry Smith   }
5641e07b27eSBarry Smith 
5651e07b27eSBarry Smith   /* setup */
566aaa7a805SDave May   if (!pc->setupcalled && sred->pctelescope_setup_type) {
5679566063dSJacob Faibussowitsch     PetscCall(sred->pctelescope_setup_type(pc,sred));
5681e07b27eSBarry Smith   }
5691e07b27eSBarry Smith   /* update */
5701e07b27eSBarry Smith   if (!pc->setupcalled) {
5711e07b27eSBarry Smith     if (sred->pctelescope_matcreate_type) {
5729566063dSJacob Faibussowitsch       PetscCall(sred->pctelescope_matcreate_type(pc,sred,MAT_INITIAL_MATRIX,&sred->Bred));
5731e07b27eSBarry Smith     }
574*1baa6e33SBarry Smith     if (sred->pctelescope_matnullspacecreate_type) PetscCall(sred->pctelescope_matnullspacecreate_type(pc,sred,sred->Bred));
5751e07b27eSBarry Smith   } else {
5761e07b27eSBarry Smith     if (sred->pctelescope_matcreate_type) {
5779566063dSJacob Faibussowitsch       PetscCall(sred->pctelescope_matcreate_type(pc,sred,MAT_REUSE_MATRIX,&sred->Bred));
5781e07b27eSBarry Smith     }
5791e07b27eSBarry Smith   }
5801e07b27eSBarry Smith 
5811e07b27eSBarry Smith   /* common - no construction */
58257f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
5839566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(sred->ksp,sred->Bred,sred->Bred));
5841e07b27eSBarry Smith     if (pc->setfromoptionscalled && !pc->setupcalled) {
5859566063dSJacob Faibussowitsch       PetscCall(KSPSetFromOptions(sred->ksp));
5861e07b27eSBarry Smith     }
5871e07b27eSBarry Smith   }
5881e07b27eSBarry Smith   PetscFunctionReturn(0);
5891e07b27eSBarry Smith }
5901e07b27eSBarry Smith 
5911e07b27eSBarry Smith static PetscErrorCode PCApply_Telescope(PC pc,Vec x,Vec y)
5921e07b27eSBarry Smith {
5931e07b27eSBarry Smith   PC_Telescope      sred = (PC_Telescope)pc->data;
5941e07b27eSBarry Smith   Vec               xtmp,xred,yred;
59513c30530SDave May   PetscInt          i,st,ed;
5961e07b27eSBarry Smith   VecScatter        scatter;
5971e07b27eSBarry Smith   PetscScalar       *array;
5981e07b27eSBarry Smith   const PetscScalar *x_array;
5991e07b27eSBarry Smith 
6001e07b27eSBarry Smith   PetscFunctionBegin;
6019566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(citation,&cited));
602bf00f589SPatrick Sanan 
6031e07b27eSBarry Smith   xtmp    = sred->xtmp;
6041e07b27eSBarry Smith   scatter = sred->scatter;
6051e07b27eSBarry Smith   xred    = sred->xred;
6061e07b27eSBarry Smith   yred    = sred->yred;
6071e07b27eSBarry Smith 
6081e07b27eSBarry Smith   /* pull in vector x->xtmp */
6099566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(scatter,x,xtmp,INSERT_VALUES,SCATTER_FORWARD));
6109566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(scatter,x,xtmp,INSERT_VALUES,SCATTER_FORWARD));
6111e07b27eSBarry Smith 
612bf00f589SPatrick Sanan   /* copy vector entries into xred */
6139566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(xtmp,&x_array));
6141e07b27eSBarry Smith   if (xred) {
6151e07b27eSBarry Smith     PetscScalar *LA_xred;
6169566063dSJacob Faibussowitsch     PetscCall(VecGetOwnershipRange(xred,&st,&ed));
6179566063dSJacob Faibussowitsch     PetscCall(VecGetArray(xred,&LA_xred));
6181e07b27eSBarry Smith     for (i=0; i<ed-st; i++) {
6191e07b27eSBarry Smith       LA_xred[i] = x_array[i];
6201e07b27eSBarry Smith     }
6219566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(xred,&LA_xred));
6221e07b27eSBarry Smith   }
6239566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(xtmp,&x_array));
6241e07b27eSBarry Smith   /* solve */
62557f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
6269566063dSJacob Faibussowitsch     PetscCall(KSPSolve(sred->ksp,xred,yred));
6279566063dSJacob Faibussowitsch     PetscCall(KSPCheckSolve(sred->ksp,pc,yred));
6281e07b27eSBarry Smith   }
6291e07b27eSBarry Smith   /* return vector */
6309566063dSJacob Faibussowitsch   PetscCall(VecGetArray(xtmp,&array));
6311e07b27eSBarry Smith   if (yred) {
6321e07b27eSBarry Smith     const PetscScalar *LA_yred;
6339566063dSJacob Faibussowitsch     PetscCall(VecGetOwnershipRange(yred,&st,&ed));
6349566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(yred,&LA_yred));
6351e07b27eSBarry Smith     for (i=0; i<ed-st; i++) {
6361e07b27eSBarry Smith       array[i] = LA_yred[i];
6371e07b27eSBarry Smith     }
6389566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(yred,&LA_yred));
6391e07b27eSBarry Smith   }
6409566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(xtmp,&array));
6419566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(scatter,xtmp,y,INSERT_VALUES,SCATTER_REVERSE));
6429566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(scatter,xtmp,y,INSERT_VALUES,SCATTER_REVERSE));
6431e07b27eSBarry Smith   PetscFunctionReturn(0);
6441e07b27eSBarry Smith }
6451e07b27eSBarry Smith 
646f650675bSDave 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)
647f650675bSDave May {
648f650675bSDave May   PC_Telescope      sred = (PC_Telescope)pc->data;
649a1d91a28SDave May   Vec               xtmp,yred;
650f650675bSDave May   PetscInt          i,st,ed;
651f650675bSDave May   VecScatter        scatter;
652f650675bSDave May   const PetscScalar *x_array;
653f650675bSDave May   PetscBool         default_init_guess_value;
654f650675bSDave May 
655f650675bSDave May   PetscFunctionBegin;
656f650675bSDave May   xtmp    = sred->xtmp;
657f650675bSDave May   scatter = sred->scatter;
658f650675bSDave May   yred    = sred->yred;
659f650675bSDave May 
66008401ef6SPierre Jolivet   PetscCheck(its <= 1,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCApplyRichardson_Telescope only supports max_it = 1");
661f650675bSDave May   *reason = (PCRichardsonConvergedReason)0;
662f650675bSDave May 
663f650675bSDave May   if (!zeroguess) {
6649566063dSJacob Faibussowitsch     PetscCall(PetscInfo(pc,"PCTelescope: Scattering y for non-zero initial guess\n"));
665f650675bSDave May     /* pull in vector y->xtmp */
6669566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(scatter,y,xtmp,INSERT_VALUES,SCATTER_FORWARD));
6679566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(scatter,y,xtmp,INSERT_VALUES,SCATTER_FORWARD));
668f650675bSDave May 
669bf00f589SPatrick Sanan     /* copy vector entries into xred */
6709566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(xtmp,&x_array));
671f650675bSDave May     if (yred) {
672f650675bSDave May       PetscScalar *LA_yred;
6739566063dSJacob Faibussowitsch       PetscCall(VecGetOwnershipRange(yred,&st,&ed));
6749566063dSJacob Faibussowitsch       PetscCall(VecGetArray(yred,&LA_yred));
675f650675bSDave May       for (i=0; i<ed-st; i++) {
676f650675bSDave May         LA_yred[i] = x_array[i];
677f650675bSDave May       }
6789566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(yred,&LA_yred));
679f650675bSDave May     }
6809566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(xtmp,&x_array));
681f650675bSDave May   }
682f650675bSDave May 
68357f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
6849566063dSJacob Faibussowitsch     PetscCall(KSPGetInitialGuessNonzero(sred->ksp,&default_init_guess_value));
6859566063dSJacob Faibussowitsch     if (!zeroguess) PetscCall(KSPSetInitialGuessNonzero(sred->ksp,PETSC_TRUE));
686f650675bSDave May   }
687f650675bSDave May 
6889566063dSJacob Faibussowitsch   PetscCall(PCApply_Telescope(pc,x,y));
689f650675bSDave May 
69057f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
6919566063dSJacob Faibussowitsch     PetscCall(KSPSetInitialGuessNonzero(sred->ksp,default_init_guess_value));
692f650675bSDave May   }
693f650675bSDave May 
694f650675bSDave May   if (!*reason) *reason = PCRICHARDSON_CONVERGED_ITS;
695f650675bSDave May   *outits = 1;
696f650675bSDave May   PetscFunctionReturn(0);
697f650675bSDave May }
698f650675bSDave May 
6991e07b27eSBarry Smith static PetscErrorCode PCReset_Telescope(PC pc)
7001e07b27eSBarry Smith {
7011e07b27eSBarry Smith   PC_Telescope   sred = (PC_Telescope)pc->data;
7021e07b27eSBarry Smith 
703362febeeSStefano Zampini   PetscFunctionBegin;
7049566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&sred->isin));
7059566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&sred->scatter));
7069566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&sred->xred));
7079566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&sred->yred));
7089566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&sred->xtmp));
7099566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&sred->Bred));
7109566063dSJacob Faibussowitsch   PetscCall(KSPReset(sred->ksp));
711*1baa6e33SBarry Smith   if (sred->pctelescope_reset_type) PetscCall(sred->pctelescope_reset_type(pc));
7121e07b27eSBarry Smith   PetscFunctionReturn(0);
7131e07b27eSBarry Smith }
7141e07b27eSBarry Smith 
7151e07b27eSBarry Smith static PetscErrorCode PCDestroy_Telescope(PC pc)
7161e07b27eSBarry Smith {
7171e07b27eSBarry Smith   PC_Telescope   sred = (PC_Telescope)pc->data;
7181e07b27eSBarry Smith 
7191e07b27eSBarry Smith   PetscFunctionBegin;
7209566063dSJacob Faibussowitsch   PetscCall(PCReset_Telescope(pc));
7219566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&sred->ksp));
7229566063dSJacob Faibussowitsch   PetscCall(PetscSubcommDestroy(&sred->psubcomm));
7239566063dSJacob Faibussowitsch   PetscCall(PetscFree(sred->dm_ctx));
7242e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetKSP_C",NULL));
7252e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetSubcommType_C",NULL));
7262e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetSubcommType_C",NULL));
7272e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetReductionFactor_C",NULL));
7282e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetReductionFactor_C",NULL));
7292e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetIgnoreDM_C",NULL));
7302e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetIgnoreDM_C",NULL));
7312e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetIgnoreKSPComputeOperators_C",NULL));
7322e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetIgnoreKSPComputeOperators_C",NULL));
7332e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetDM_C",NULL));
7342e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetUseCoarseDM_C",NULL));
7352e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetUseCoarseDM_C",NULL));
7369566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
7371e07b27eSBarry Smith   PetscFunctionReturn(0);
7381e07b27eSBarry Smith }
7391e07b27eSBarry Smith 
7404416b707SBarry Smith static PetscErrorCode PCSetFromOptions_Telescope(PetscOptionItems *PetscOptionsObject,PC pc)
7411e07b27eSBarry Smith {
7421e07b27eSBarry Smith   PC_Telescope     sred = (PC_Telescope)pc->data;
7431e07b27eSBarry Smith   MPI_Comm         comm;
7441e07b27eSBarry Smith   PetscMPIInt      size;
74548a10b22SPatrick Sanan   PetscBool        flg;
74648a10b22SPatrick Sanan   PetscSubcommType subcommtype;
7471e07b27eSBarry Smith 
7481e07b27eSBarry Smith   PetscFunctionBegin;
7499566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)pc,&comm));
7509566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm,&size));
751d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject,"Telescope options");
7529566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-pc_telescope_subcomm_type","Subcomm type (interlaced or contiguous)","PCTelescopeSetSubcommType",PetscSubcommTypes,(PetscEnum)sred->subcommtype,(PetscEnum*)&subcommtype,&flg));
753*1baa6e33SBarry Smith   if (flg) PetscCall(PCTelescopeSetSubcommType(pc,subcommtype));
7549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_telescope_reduction_factor","Factor to reduce comm size by","PCTelescopeSetReductionFactor",sred->redfactor,&sred->redfactor,NULL));
75508401ef6SPierre Jolivet   PetscCheck(sred->redfactor <= size,comm,PETSC_ERR_ARG_WRONG,"-pc_telescope_reduction_factor <= comm size");
7569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_telescope_ignore_dm","Ignore any DM attached to the PC","PCTelescopeSetIgnoreDM",sred->ignore_dm,&sred->ignore_dm,NULL));
7579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_telescope_ignore_kspcomputeoperators","Ignore method used to compute A","PCTelescopeSetIgnoreKSPComputeOperators",sred->ignore_kspcomputeoperators,&sred->ignore_kspcomputeoperators,NULL));
7589566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_telescope_use_coarse_dm","Define sub-communicator from the coarse DM","PCTelescopeSetUseCoarseDM",sred->use_coarse_dm,&sred->use_coarse_dm,NULL));
759d0609cedSBarry Smith   PetscOptionsHeadEnd();
7601e07b27eSBarry Smith   PetscFunctionReturn(0);
7611e07b27eSBarry Smith }
7621e07b27eSBarry Smith 
7631e07b27eSBarry Smith /* PC simplementation specific API's */
7641e07b27eSBarry Smith 
7651e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetKSP_Telescope(PC pc,KSP *ksp)
7661e07b27eSBarry Smith {
7671e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
768bd49479cSSatish Balay   PetscFunctionBegin;
7691e07b27eSBarry Smith   if (ksp) *ksp = red->ksp;
770bd49479cSSatish Balay   PetscFunctionReturn(0);
7711e07b27eSBarry Smith }
7721e07b27eSBarry Smith 
77348a10b22SPatrick Sanan static PetscErrorCode PCTelescopeGetSubcommType_Telescope(PC pc,PetscSubcommType *subcommtype)
77448a10b22SPatrick Sanan {
77548a10b22SPatrick Sanan   PC_Telescope red = (PC_Telescope)pc->data;
77648a10b22SPatrick Sanan   PetscFunctionBegin;
77748a10b22SPatrick Sanan   if (subcommtype) *subcommtype = red->subcommtype;
77848a10b22SPatrick Sanan   PetscFunctionReturn(0);
77948a10b22SPatrick Sanan }
78048a10b22SPatrick Sanan 
78148a10b22SPatrick Sanan static PetscErrorCode PCTelescopeSetSubcommType_Telescope(PC pc,PetscSubcommType subcommtype)
78248a10b22SPatrick Sanan {
78348a10b22SPatrick Sanan   PC_Telescope     red = (PC_Telescope)pc->data;
78448a10b22SPatrick Sanan 
78548a10b22SPatrick Sanan   PetscFunctionBegin;
78628b400f6SJacob Faibussowitsch   PetscCheck(!pc->setupcalled,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"You cannot change the subcommunicator type for PCTelescope after it has been set up.");
78748a10b22SPatrick Sanan   red->subcommtype = subcommtype;
78848a10b22SPatrick Sanan   PetscFunctionReturn(0);
78948a10b22SPatrick Sanan }
79048a10b22SPatrick Sanan 
7911e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetReductionFactor_Telescope(PC pc,PetscInt *fact)
7921e07b27eSBarry Smith {
7931e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
794bd49479cSSatish Balay   PetscFunctionBegin;
7951e07b27eSBarry Smith   if (fact) *fact = red->redfactor;
796bd49479cSSatish Balay   PetscFunctionReturn(0);
7971e07b27eSBarry Smith }
7981e07b27eSBarry Smith 
7991e07b27eSBarry Smith static PetscErrorCode PCTelescopeSetReductionFactor_Telescope(PC pc,PetscInt fact)
8001e07b27eSBarry Smith {
8011e07b27eSBarry Smith   PC_Telescope     red = (PC_Telescope)pc->data;
8021e07b27eSBarry Smith   PetscMPIInt      size;
8031e07b27eSBarry Smith 
804bd49479cSSatish Balay   PetscFunctionBegin;
8059566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size));
80663a3b9bcSJacob Faibussowitsch   PetscCheck(fact > 0,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Reduction factor of telescoping PC %" PetscInt_FMT " must be positive",fact);
80763a3b9bcSJacob Faibussowitsch   PetscCheck(fact <= size,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Reduction factor of telescoping PC %" PetscInt_FMT " must be <= comm.size",fact);
8081e07b27eSBarry Smith   red->redfactor = fact;
809bd49479cSSatish Balay   PetscFunctionReturn(0);
8101e07b27eSBarry Smith }
8111e07b27eSBarry Smith 
8121e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetIgnoreDM_Telescope(PC pc,PetscBool *v)
8131e07b27eSBarry Smith {
8141e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
815bd49479cSSatish Balay   PetscFunctionBegin;
8161e07b27eSBarry Smith   if (v) *v = red->ignore_dm;
817bd49479cSSatish Balay   PetscFunctionReturn(0);
8181e07b27eSBarry Smith }
81948a10b22SPatrick Sanan 
8201e07b27eSBarry Smith static PetscErrorCode PCTelescopeSetIgnoreDM_Telescope(PC pc,PetscBool v)
8211e07b27eSBarry Smith {
8221e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
823bd49479cSSatish Balay   PetscFunctionBegin;
8241e07b27eSBarry Smith   red->ignore_dm = v;
825bd49479cSSatish Balay   PetscFunctionReturn(0);
8261e07b27eSBarry Smith }
8271e07b27eSBarry Smith 
8288d9f7141SDave May static PetscErrorCode PCTelescopeGetUseCoarseDM_Telescope(PC pc,PetscBool *v)
8298d9f7141SDave May {
8308d9f7141SDave May   PC_Telescope red = (PC_Telescope)pc->data;
8318d9f7141SDave May   PetscFunctionBegin;
8328d9f7141SDave May   if (v) *v = red->use_coarse_dm;
8338d9f7141SDave May   PetscFunctionReturn(0);
8348d9f7141SDave May }
8358d9f7141SDave May 
8368d9f7141SDave May static PetscErrorCode PCTelescopeSetUseCoarseDM_Telescope(PC pc,PetscBool v)
8378d9f7141SDave May {
8388d9f7141SDave May   PC_Telescope red = (PC_Telescope)pc->data;
8398d9f7141SDave May   PetscFunctionBegin;
8408d9f7141SDave May   red->use_coarse_dm = v;
8418d9f7141SDave May   PetscFunctionReturn(0);
8428d9f7141SDave May }
8438d9f7141SDave May 
8440ae7c45bSDave May static PetscErrorCode PCTelescopeGetIgnoreKSPComputeOperators_Telescope(PC pc,PetscBool *v)
8450ae7c45bSDave May {
8460ae7c45bSDave May   PC_Telescope red = (PC_Telescope)pc->data;
8470ae7c45bSDave May   PetscFunctionBegin;
8480ae7c45bSDave May   if (v) *v = red->ignore_kspcomputeoperators;
8490ae7c45bSDave May   PetscFunctionReturn(0);
8500ae7c45bSDave May }
85148a10b22SPatrick Sanan 
8520ae7c45bSDave May static PetscErrorCode PCTelescopeSetIgnoreKSPComputeOperators_Telescope(PC pc,PetscBool v)
8530ae7c45bSDave May {
8540ae7c45bSDave May   PC_Telescope red = (PC_Telescope)pc->data;
8550ae7c45bSDave May   PetscFunctionBegin;
8560ae7c45bSDave May   red->ignore_kspcomputeoperators = v;
8570ae7c45bSDave May   PetscFunctionReturn(0);
8580ae7c45bSDave May }
8590ae7c45bSDave May 
8601e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetDM_Telescope(PC pc,DM *dm)
8611e07b27eSBarry Smith {
8621e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
863bd49479cSSatish Balay   PetscFunctionBegin;
8641e07b27eSBarry Smith   *dm = private_PCTelescopeGetSubDM(red);
865bd49479cSSatish Balay   PetscFunctionReturn(0);
8661e07b27eSBarry Smith }
8671e07b27eSBarry Smith 
8681e07b27eSBarry Smith /*@
8691e07b27eSBarry Smith  PCTelescopeGetKSP - Gets the KSP created by the telescoping PC.
8701e07b27eSBarry Smith 
8711e07b27eSBarry Smith  Not Collective
8721e07b27eSBarry Smith 
8731e07b27eSBarry Smith  Input Parameter:
8741e07b27eSBarry Smith .  pc - the preconditioner context
8751e07b27eSBarry Smith 
8761e07b27eSBarry Smith  Output Parameter:
8771e07b27eSBarry Smith .  subksp - the KSP defined the smaller set of processes
8781e07b27eSBarry Smith 
8791e07b27eSBarry Smith  Level: advanced
8801e07b27eSBarry Smith 
8811e07b27eSBarry Smith @*/
8821e07b27eSBarry Smith PetscErrorCode PCTelescopeGetKSP(PC pc,KSP *subksp)
8831e07b27eSBarry Smith {
884bd49479cSSatish Balay   PetscFunctionBegin;
885cac4c232SBarry Smith   PetscUseMethod(pc,"PCTelescopeGetKSP_C",(PC,KSP*),(pc,subksp));
886bd49479cSSatish Balay   PetscFunctionReturn(0);
8871e07b27eSBarry Smith }
8881e07b27eSBarry Smith 
8891e07b27eSBarry Smith /*@
8901e07b27eSBarry Smith  PCTelescopeGetReductionFactor - Gets the factor by which the original number of processes has been reduced by.
8911e07b27eSBarry Smith 
8921e07b27eSBarry Smith  Not Collective
8931e07b27eSBarry Smith 
8941e07b27eSBarry Smith  Input Parameter:
8951e07b27eSBarry Smith .  pc - the preconditioner context
8961e07b27eSBarry Smith 
8971e07b27eSBarry Smith  Output Parameter:
8981e07b27eSBarry Smith .  fact - the reduction factor
8991e07b27eSBarry Smith 
9001e07b27eSBarry Smith  Level: advanced
9011e07b27eSBarry Smith 
9021e07b27eSBarry Smith @*/
9031e07b27eSBarry Smith PetscErrorCode PCTelescopeGetReductionFactor(PC pc,PetscInt *fact)
9041e07b27eSBarry Smith {
905bd49479cSSatish Balay   PetscFunctionBegin;
906cac4c232SBarry Smith   PetscUseMethod(pc,"PCTelescopeGetReductionFactor_C",(PC,PetscInt*),(pc,fact));
907bd49479cSSatish Balay   PetscFunctionReturn(0);
9081e07b27eSBarry Smith }
9091e07b27eSBarry Smith 
9101e07b27eSBarry Smith /*@
9111e07b27eSBarry Smith  PCTelescopeSetReductionFactor - Sets the factor by which the original number of processes has been reduced by.
9121e07b27eSBarry Smith 
9131e07b27eSBarry Smith  Not Collective
9141e07b27eSBarry Smith 
9151e07b27eSBarry Smith  Input Parameter:
9161e07b27eSBarry Smith .  pc - the preconditioner context
9171e07b27eSBarry Smith 
9181e07b27eSBarry Smith  Output Parameter:
9191e07b27eSBarry Smith .  fact - the reduction factor
9201e07b27eSBarry Smith 
9211e07b27eSBarry Smith  Level: advanced
9221e07b27eSBarry Smith 
9231e07b27eSBarry Smith @*/
9241e07b27eSBarry Smith PetscErrorCode PCTelescopeSetReductionFactor(PC pc,PetscInt fact)
9251e07b27eSBarry Smith {
926bd49479cSSatish Balay   PetscFunctionBegin;
927cac4c232SBarry Smith   PetscTryMethod(pc,"PCTelescopeSetReductionFactor_C",(PC,PetscInt),(pc,fact));
928bd49479cSSatish Balay   PetscFunctionReturn(0);
9291e07b27eSBarry Smith }
9301e07b27eSBarry Smith 
9311e07b27eSBarry Smith /*@
9321e07b27eSBarry Smith  PCTelescopeGetIgnoreDM - Get the flag indicating if any DM attached to the PC will be used.
9331e07b27eSBarry Smith 
9341e07b27eSBarry Smith  Not Collective
9351e07b27eSBarry Smith 
9361e07b27eSBarry Smith  Input Parameter:
9371e07b27eSBarry Smith .  pc - the preconditioner context
9381e07b27eSBarry Smith 
9391e07b27eSBarry Smith  Output Parameter:
9401e07b27eSBarry Smith .  v - the flag
9411e07b27eSBarry Smith 
9421e07b27eSBarry Smith  Level: advanced
9431e07b27eSBarry Smith 
9441e07b27eSBarry Smith @*/
9451e07b27eSBarry Smith PetscErrorCode PCTelescopeGetIgnoreDM(PC pc,PetscBool *v)
9461e07b27eSBarry Smith {
947bd49479cSSatish Balay   PetscFunctionBegin;
948cac4c232SBarry Smith   PetscUseMethod(pc,"PCTelescopeGetIgnoreDM_C",(PC,PetscBool*),(pc,v));
949bd49479cSSatish Balay   PetscFunctionReturn(0);
9501e07b27eSBarry Smith }
9511e07b27eSBarry Smith 
9521e07b27eSBarry Smith /*@
9531e07b27eSBarry Smith  PCTelescopeSetIgnoreDM - Set a flag to ignore any DM attached to the PC.
9541e07b27eSBarry Smith 
9551e07b27eSBarry Smith  Not Collective
9561e07b27eSBarry Smith 
9571e07b27eSBarry Smith  Input Parameter:
9581e07b27eSBarry Smith .  pc - the preconditioner context
9591e07b27eSBarry Smith 
9601e07b27eSBarry Smith  Output Parameter:
9611e07b27eSBarry Smith .  v - Use PETSC_TRUE to ignore any DM
9621e07b27eSBarry Smith 
9631e07b27eSBarry Smith  Level: advanced
9641e07b27eSBarry Smith 
9651e07b27eSBarry Smith @*/
966bfd6bcc6SSatish Balay PetscErrorCode PCTelescopeSetIgnoreDM(PC pc,PetscBool v)
9671e07b27eSBarry Smith {
968bd49479cSSatish Balay   PetscFunctionBegin;
969cac4c232SBarry Smith   PetscTryMethod(pc,"PCTelescopeSetIgnoreDM_C",(PC,PetscBool),(pc,v));
970bd49479cSSatish Balay   PetscFunctionReturn(0);
9711e07b27eSBarry Smith }
9721e07b27eSBarry Smith 
9731e07b27eSBarry Smith /*@
9748d9f7141SDave May  PCTelescopeGetUseCoarseDM - Get the flag indicating if the coarse DM attached to DM associated with the PC will be used.
9758d9f7141SDave May 
9768d9f7141SDave May  Not Collective
9778d9f7141SDave May 
9788d9f7141SDave May  Input Parameter:
9798d9f7141SDave May .  pc - the preconditioner context
9808d9f7141SDave May 
9818d9f7141SDave May  Output Parameter:
9828d9f7141SDave May .  v - the flag
9838d9f7141SDave May 
9848d9f7141SDave May  Level: advanced
9858d9f7141SDave May 
9868d9f7141SDave May @*/
9878d9f7141SDave May PetscErrorCode PCTelescopeGetUseCoarseDM(PC pc,PetscBool *v)
9888d9f7141SDave May {
9898d9f7141SDave May   PetscFunctionBegin;
990cac4c232SBarry Smith   PetscUseMethod(pc,"PCTelescopeGetUseCoarseDM_C",(PC,PetscBool*),(pc,v));
9918d9f7141SDave May   PetscFunctionReturn(0);
9928d9f7141SDave May }
9938d9f7141SDave May 
9948d9f7141SDave May /*@
9958d9f7141SDave May  PCTelescopeSetUseCoarseDM - Set a flag to query the DM attached to the PC if it also has a coarse DM
9968d9f7141SDave May 
9978d9f7141SDave May  Not Collective
9988d9f7141SDave May 
9998d9f7141SDave May  Input Parameter:
10008d9f7141SDave May .  pc - the preconditioner context
10018d9f7141SDave May 
10028d9f7141SDave May  Output Parameter:
1003aaa7a805SDave May .  v - Use PETSC_FALSE to ignore any coarse DM
10048d9f7141SDave May 
10058d9f7141SDave May  Notes:
10068d9f7141SDave May  When you have specified to use a coarse DM, the communicator used to create the sub-KSP within PCTelescope
10078d9f7141SDave May  will be that of the coarse DM. Hence the flags -pc_telescope_reduction_factor and
10088d9f7141SDave May  -pc_telescope_subcomm_type will no longer have any meaning.
10098d9f7141SDave May  It is required that the communicator associated with the parent (fine) and the coarse DM are of different sizes.
10108d9f7141SDave May  An error will occur of the size of the communicator associated with the coarse DM
10118d9f7141SDave May  is the same as that of the parent DM.
10128d9f7141SDave May  Furthermore, it is required that the communicator on the coarse DM is a sub-communicator of the parent.
10138d9f7141SDave May  This will be checked at the time the preconditioner is setup and an error will occur if
10148d9f7141SDave May  the coarse DM does not define a sub-communicator of that used by the parent DM.
10158d9f7141SDave May 
10168d9f7141SDave May  The particular Telescope setup invoked when using a coarse DM is agnostic with respect to the type of
10178d9f7141SDave May  the DM used (e.g. it supports DMSHELL, DMPLEX, etc).
10188d9f7141SDave May 
10198d9f7141SDave May  Support is currently only provided for the case when you are using KSPSetComputeOperators()
10208d9f7141SDave May 
10218d9f7141SDave 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.
10228d9f7141SDave May  In the user code, this is achieved via
10238d9f7141SDave May .vb
10248d9f7141SDave May    {
10258d9f7141SDave May      DM dm_fine;
10268d9f7141SDave May      PetscObjectCompose((PetscObject)dm_fine,"PCTelescopeFieldScatter",your_field_scatter_method);
10278d9f7141SDave May    }
10288d9f7141SDave May .ve
10298d9f7141SDave May  The signature of the user provided field scatter method is
10308d9f7141SDave May .vb
10318d9f7141SDave May    PetscErrorCode your_field_scatter_method(DM dm_fine,Vec x_fine,ScatterMode mode,DM dm_coarse,Vec x_coarse);
10328d9f7141SDave May .ve
10338d9f7141SDave May  The user must provide support for both mode = SCATTER_FORWARD and mode = SCATTER_REVERSE.
10348d9f7141SDave May  SCATTER_FORWARD implies the direction of transfer is from the parent (fine) DM to the coarse DM.
10358d9f7141SDave May 
10368d9f7141SDave May  Optionally, the user may also compose a function with the parent DM to facilitate the transfer
10378d9f7141SDave May  of state variables between the fine and coarse DMs.
10388d9f7141SDave May  In the context of a finite element discretization, an example state variable might be
10398d9f7141SDave May  values associated with quadrature points within each element.
10408d9f7141SDave May  A user provided state scatter method is composed via
10418d9f7141SDave May .vb
10428d9f7141SDave May    {
10438d9f7141SDave May      DM dm_fine;
10448d9f7141SDave May      PetscObjectCompose((PetscObject)dm_fine,"PCTelescopeStateScatter",your_state_scatter_method);
10458d9f7141SDave May    }
10468d9f7141SDave May .ve
10478d9f7141SDave May  The signature of the user provided state scatter method is
10488d9f7141SDave May .vb
10498d9f7141SDave May    PetscErrorCode your_state_scatter_method(DM dm_fine,ScatterMode mode,DM dm_coarse);
10508d9f7141SDave May .ve
10518d9f7141SDave May  SCATTER_FORWARD implies the direction of transfer is from the fine DM to the coarse DM.
10528d9f7141SDave May  The user is only required to support mode = SCATTER_FORWARD.
10538d9f7141SDave May  No assumption is made about the data type of the state variables.
10548d9f7141SDave May  These must be managed by the user and must be accessible from the DM.
10558d9f7141SDave May 
10568d9f7141SDave May  Care must be taken in defining the user context passed to KSPSetComputeOperators() which is to be
10578d9f7141SDave May  associated with the sub-KSP residing within PCTelescope.
10588d9f7141SDave May  In general, PCTelescope assumes that the context on the fine and coarse DM used with
10598d9f7141SDave May  KSPSetComputeOperators() should be "similar" in type or origin.
10608d9f7141SDave May  Specifically the following rules are used to infer what context on the sub-KSP should be.
10618d9f7141SDave May 
10628d9f7141SDave May  First the contexts from the KSP and the fine and coarse DMs are retrieved.
10638d9f7141SDave May  Note that the special case of a DMSHELL context is queried.
10648d9f7141SDave May 
10658d9f7141SDave May .vb
10668d9f7141SDave May    DMKSPGetComputeOperators(dm_fine,&dmfine_kspfunc,&dmfine_kspctx);
10678d9f7141SDave May    DMGetApplicationContext(dm_fine,&dmfine_appctx);
10688d9f7141SDave May    DMShellGetContext(dm_fine,&dmfine_shellctx);
10698d9f7141SDave May 
10708d9f7141SDave May    DMGetApplicationContext(dm_coarse,&dmcoarse_appctx);
10718d9f7141SDave May    DMShellGetContext(dm_coarse,&dmcoarse_shellctx);
10728d9f7141SDave May .ve
10738d9f7141SDave May 
10748d9f7141SDave May  The following rules are then enforced:
10758d9f7141SDave May 
10768d9f7141SDave May  1. If dmfine_kspctx = NULL, then we provide a NULL pointer as the context for the sub-KSP:
10778d9f7141SDave May  KSPSetComputeOperators(sub_ksp,dmfine_kspfunc,NULL);
10788d9f7141SDave May 
10798d9f7141SDave May  2. If dmfine_kspctx != NULL and dmfine_kspctx == dmfine_appctx,
10808d9f7141SDave May  check that dmcoarse_appctx is also non-NULL. If this is true, then:
10818d9f7141SDave May  KSPSetComputeOperators(sub_ksp,dmfine_kspfunc,dmcoarse_appctx);
10828d9f7141SDave May 
10838d9f7141SDave May  3. If dmfine_kspctx != NULL and dmfine_kspctx == dmfine_shellctx,
10848d9f7141SDave May  check that dmcoarse_shellctx is also non-NULL. If this is true, then:
10858d9f7141SDave May  KSPSetComputeOperators(sub_ksp,dmfine_kspfunc,dmcoarse_shellctx);
10868d9f7141SDave May 
10878d9f7141SDave May  If neither of the above three tests passed, then PCTelescope cannot safely determine what
10888d9f7141SDave May  context should be provided to KSPSetComputeOperators() for use with the sub-KSP.
10898d9f7141SDave May  In this case, an additional mechanism is provided via a composed function which will return
10908d9f7141SDave May  the actual context to be used. To use this feature you must compose the "getter" function
10918d9f7141SDave May  with the coarse DM, e.g.
10928d9f7141SDave May .vb
10938d9f7141SDave May    {
10948d9f7141SDave May      DM dm_coarse;
10958d9f7141SDave May      PetscObjectCompose((PetscObject)dm_coarse,"PCTelescopeGetCoarseDMKSPContext",your_coarse_context_getter);
10968d9f7141SDave May    }
10978d9f7141SDave May .ve
10988d9f7141SDave May  The signature of the user provided method is
10998d9f7141SDave May .vb
11008d9f7141SDave May    PetscErrorCode your_coarse_context_getter(DM dm_coarse,void **your_kspcontext);
11018d9f7141SDave May .ve
11028d9f7141SDave May 
11038d9f7141SDave May  Level: advanced
11048d9f7141SDave May 
11058d9f7141SDave May @*/
11068d9f7141SDave May PetscErrorCode PCTelescopeSetUseCoarseDM(PC pc,PetscBool v)
11078d9f7141SDave May {
11088d9f7141SDave May   PetscFunctionBegin;
1109cac4c232SBarry Smith   PetscTryMethod(pc,"PCTelescopeSetUseCoarseDM_C",(PC,PetscBool),(pc,v));
11108d9f7141SDave May   PetscFunctionReturn(0);
11118d9f7141SDave May }
11128d9f7141SDave May 
11138d9f7141SDave May /*@
11140ae7c45bSDave May  PCTelescopeGetIgnoreKSPComputeOperators - Get the flag indicating if KSPComputeOperators will be used.
11150ae7c45bSDave May 
11160ae7c45bSDave May  Not Collective
11170ae7c45bSDave May 
11180ae7c45bSDave May  Input Parameter:
11190ae7c45bSDave May .  pc - the preconditioner context
11200ae7c45bSDave May 
11210ae7c45bSDave May  Output Parameter:
11220ae7c45bSDave May .  v - the flag
11230ae7c45bSDave May 
11240ae7c45bSDave May  Level: advanced
11250ae7c45bSDave May 
11260ae7c45bSDave May @*/
11270ae7c45bSDave May PetscErrorCode PCTelescopeGetIgnoreKSPComputeOperators(PC pc,PetscBool *v)
11280ae7c45bSDave May {
11290ae7c45bSDave May   PetscFunctionBegin;
1130cac4c232SBarry Smith   PetscUseMethod(pc,"PCTelescopeGetIgnoreKSPComputeOperators_C",(PC,PetscBool*),(pc,v));
11310ae7c45bSDave May   PetscFunctionReturn(0);
11320ae7c45bSDave May }
11330ae7c45bSDave May 
11340ae7c45bSDave May /*@
11350ae7c45bSDave May  PCTelescopeSetIgnoreKSPComputeOperators - Set a flag to ignore KSPComputeOperators.
11360ae7c45bSDave May 
11370ae7c45bSDave May  Not Collective
11380ae7c45bSDave May 
11390ae7c45bSDave May  Input Parameter:
11400ae7c45bSDave May .  pc - the preconditioner context
11410ae7c45bSDave May 
11420ae7c45bSDave May  Output Parameter:
1143a954d8f4SDave May .  v - Use PETSC_TRUE to ignore the method (if defined) set via KSPSetComputeOperators on pc
11440ae7c45bSDave May 
11450ae7c45bSDave May  Level: advanced
11460ae7c45bSDave May 
11470ae7c45bSDave May @*/
11480ae7c45bSDave May PetscErrorCode PCTelescopeSetIgnoreKSPComputeOperators(PC pc,PetscBool v)
11490ae7c45bSDave May {
11500ae7c45bSDave May   PetscFunctionBegin;
1151cac4c232SBarry Smith   PetscTryMethod(pc,"PCTelescopeSetIgnoreKSPComputeOperators_C",(PC,PetscBool),(pc,v));
11520ae7c45bSDave May   PetscFunctionReturn(0);
11530ae7c45bSDave May }
11540ae7c45bSDave May 
11550ae7c45bSDave May /*@
11561e07b27eSBarry Smith  PCTelescopeGetDM - Get the re-partitioned DM attached to the sub KSP.
11571e07b27eSBarry Smith 
11581e07b27eSBarry Smith  Not Collective
11591e07b27eSBarry Smith 
11601e07b27eSBarry Smith  Input Parameter:
11611e07b27eSBarry Smith .  pc - the preconditioner context
11621e07b27eSBarry Smith 
11631e07b27eSBarry Smith  Output Parameter:
11641e07b27eSBarry Smith .  subdm - The re-partitioned DM
11651e07b27eSBarry Smith 
11661e07b27eSBarry Smith  Level: advanced
11671e07b27eSBarry Smith 
11681e07b27eSBarry Smith @*/
11691e07b27eSBarry Smith PetscErrorCode PCTelescopeGetDM(PC pc,DM *subdm)
11701e07b27eSBarry Smith {
1171bd49479cSSatish Balay   PetscFunctionBegin;
1172cac4c232SBarry Smith   PetscUseMethod(pc,"PCTelescopeGetDM_C",(PC,DM*),(pc,subdm));
1173bd49479cSSatish Balay   PetscFunctionReturn(0);
11741e07b27eSBarry Smith }
11751e07b27eSBarry Smith 
117648a10b22SPatrick Sanan /*@
117748a10b22SPatrick Sanan  PCTelescopeSetSubcommType - set subcommunicator type (interlaced or contiguous)
117848a10b22SPatrick Sanan 
117948a10b22SPatrick Sanan  Logically Collective
118048a10b22SPatrick Sanan 
1181d8d19677SJose E. Roman  Input Parameters:
11821dae98e4SBarry Smith +  pc - the preconditioner context
11831dae98e4SBarry Smith -  subcommtype - the subcommunicator type (see PetscSubcommType)
118448a10b22SPatrick Sanan 
118548a10b22SPatrick Sanan  Level: advanced
118648a10b22SPatrick Sanan 
1187db781477SPatrick Sanan .seealso: `PetscSubcommType`, `PetscSubcomm`, `PCTELESCOPE`
118848a10b22SPatrick Sanan @*/
118948a10b22SPatrick Sanan PetscErrorCode PCTelescopeSetSubcommType(PC pc, PetscSubcommType subcommtype)
119048a10b22SPatrick Sanan {
119148a10b22SPatrick Sanan   PetscFunctionBegin;
1192cac4c232SBarry Smith   PetscTryMethod(pc,"PCTelescopeSetSubcommType_C",(PC,PetscSubcommType),(pc,subcommtype));
119348a10b22SPatrick Sanan   PetscFunctionReturn(0);
119448a10b22SPatrick Sanan }
119548a10b22SPatrick Sanan 
119648a10b22SPatrick Sanan /*@
119748a10b22SPatrick Sanan  PCTelescopeGetSubcommType - Get the subcommunicator type (interlaced or contiguous)
119848a10b22SPatrick Sanan 
119948a10b22SPatrick Sanan  Not Collective
120048a10b22SPatrick Sanan 
120148a10b22SPatrick Sanan  Input Parameter:
120248a10b22SPatrick Sanan .  pc - the preconditioner context
120348a10b22SPatrick Sanan 
120448a10b22SPatrick Sanan  Output Parameter:
120548a10b22SPatrick Sanan .  subcommtype - the subcommunicator type (see PetscSubcommType)
120648a10b22SPatrick Sanan 
120748a10b22SPatrick Sanan  Level: advanced
120848a10b22SPatrick Sanan 
1209db781477SPatrick Sanan .seealso: `PetscSubcomm`, `PetscSubcommType`, `PCTELESCOPE`
121048a10b22SPatrick Sanan @*/
12111dae98e4SBarry Smith PetscErrorCode PCTelescopeGetSubcommType(PC pc, PetscSubcommType *subcommtype)
121248a10b22SPatrick Sanan {
121348a10b22SPatrick Sanan   PetscFunctionBegin;
1214cac4c232SBarry Smith   PetscUseMethod(pc,"PCTelescopeGetSubcommType_C",(PC,PetscSubcommType*),(pc,subcommtype));
121548a10b22SPatrick Sanan   PetscFunctionReturn(0);
121648a10b22SPatrick Sanan }
121748a10b22SPatrick Sanan 
12181e07b27eSBarry Smith /* -------------------------------------------------------------------------------------*/
12191e07b27eSBarry Smith /*MC
122000fea0ebSDave May    PCTELESCOPE - Runs a KSP solver on a sub-communicator. MPI ranks not in the sub-communicator are idle during the solve.
12211e07b27eSBarry Smith 
12221e07b27eSBarry Smith    Options Database:
122300fea0ebSDave 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.
122400fea0ebSDave May .  -pc_telescope_ignore_dm  - flag to indicate whether an attached DM should be ignored.
122500fea0ebSDave May .  -pc_telescope_subcomm_type <interlaced,contiguous> - defines the selection of MPI ranks on the sub-communicator. see PetscSubcomm for more information.
122600fea0ebSDave May .  -pc_telescope_ignore_kspcomputeoperators - flag to indicate whether KSPSetComputeOperators should be used on the sub-KSP.
122700fea0ebSDave May -  -pc_telescope_use_coarse_dm - flag to indicate whether the coarse DM should be used to define the sub-communicator.
12281e07b27eSBarry Smith 
12291e07b27eSBarry Smith    Level: advanced
12301e07b27eSBarry Smith 
12311e07b27eSBarry Smith    Notes:
123200fea0ebSDave May    Assuming that the parent preconditioner (PC) is defined on a communicator c, this implementation
123300fea0ebSDave May    creates a child sub-communicator (c') containing fewer MPI ranks than the original parent preconditioner (PC).
12346fc41876SBarry Smith    The preconditioner is deemed telescopic as it only calls KSPSolve() on a single
12358439623fSPatrick Sanan    sub-communicator, in contrast with PCREDUNDANT which calls KSPSolve() on N sub-communicators.
123600fea0ebSDave May    This means there will be MPI ranks which will be idle during the application of this preconditioner.
123700fea0ebSDave May    Additionally, in comparison with PCREDUNDANT, PCTELESCOPE can utilize an attached DM.
12386fc41876SBarry Smith 
123900fea0ebSDave May    The default type of the sub KSP (the KSP defined on c') is PREONLY.
124000fea0ebSDave May 
124100fea0ebSDave May    There are three setup mechanisms for PCTelescope. Features support by each type are described below.
124200fea0ebSDave May    In the following, we will refer to the operators B and B', these are the Bmat provided to the KSP on the
124300fea0ebSDave May    communicators c and c' respectively.
124400fea0ebSDave May 
124500fea0ebSDave May    [1] Default setup
124600fea0ebSDave May    The sub-communicator c' is created via PetscSubcommCreate().
1247a5b23f4aSJose E. Roman    Explicitly defined nullspace and near nullspace vectors will be propagated from B to B'.
124800fea0ebSDave May    Currently there is no support define nullspaces via a user supplied method (e.g. as passed to MatNullSpaceSetFunction()).
124900fea0ebSDave May    No support is provided for KSPSetComputeOperators().
125000fea0ebSDave May    Currently there is no support for the flag -pc_use_amat.
125100fea0ebSDave May 
125200fea0ebSDave May    [2] DM aware setup
125300fea0ebSDave May    If a DM is attached to the PC, it is re-partitioned on the sub-communicator c'.
125400fea0ebSDave May    c' is created via PetscSubcommCreate().
12551e07b27eSBarry Smith    Both the Bmat operator and the right hand side vector are permuted into the new DOF ordering defined by the re-partitioned DM.
12561e07b27eSBarry Smith    Currently only support for re-partitioning a DMDA is provided.
125700fea0ebSDave 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').
125800fea0ebSDave May    Currently there is no support define nullspaces via a user supplied method (e.g. as passed to MatNullSpaceSetFunction()).
125900fea0ebSDave May    Support is provided for KSPSetComputeOperators(). The user provided function and context is propagated to the sub KSP.
126000fea0ebSDave May    This is fragile since the user must ensure that their user context is valid for use on c'.
126100fea0ebSDave May    Currently there is no support for the flag -pc_use_amat.
12621e07b27eSBarry Smith 
126300fea0ebSDave May    [3] Coarse DM setup
126400fea0ebSDave May    If a DM (dmfine) is attached to the PC, dmfine is queried for a "coarse" DM (call this dmcoarse) via DMGetCoarseDM().
126500fea0ebSDave May    PCTELESCOPE will interpret the coarse DM as being defined on a sub-communicator of c.
126600fea0ebSDave May    The communicator associated with dmcoarse will define the c' to be used within PCTELESCOPE.
126700fea0ebSDave May    PCTELESCOPE will check that c' is in fact a sub-communicator of c. If it is not, an error will be reported.
126800fea0ebSDave May    The intention of this setup type is that PCTELESCOPE will use an existing (e.g. user defined) communicator hierarchy, say as would be
126900fea0ebSDave May    available with using multi-grid on unstructured meshes.
127000fea0ebSDave May    This setup will not use the command line options -pc_telescope_reduction_factor or -pc_telescope_subcomm_type.
127100fea0ebSDave 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'.
127200fea0ebSDave May    Currently there is no support define nullspaces via a user supplied method (e.g. as passed to MatNullSpaceSetFunction()).
127300fea0ebSDave May    There is no general method to permute field orderings, hence only KSPSetComputeOperators() is supported.
127400fea0ebSDave May    The user must use PetscObjectComposeFunction() with dmfine to define the method to scatter fields from dmfine to dmcoarse.
1275a5b23f4aSJose 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().
127600fea0ebSDave May    Currently there is no support for the flag -pc_use_amat.
127700fea0ebSDave May    This setup can be invoked by the option -pc_telescope_use_coarse_dm or by calling PCTelescopeSetUseCoarseDM(pc,PETSC_TRUE);
127800fea0ebSDave May    Further information about the user-provided methods required by this setup type are described here PCTelescopeSetUseCoarseDM().
12796fc41876SBarry Smith 
12806fc41876SBarry Smith    Developer Notes:
12816fc41876SBarry Smith    During PCSetup, the B operator is scattered onto c'.
12826fc41876SBarry Smith    Within PCApply, the RHS vector (x) is scattered into a redundant vector, xred (defined on c').
12838439623fSPatrick Sanan    Then, KSPSolve() is executed on the c' communicator.
12846fc41876SBarry Smith 
12856fc41876SBarry Smith    The communicator used within the telescoping preconditioner is defined by a PetscSubcomm using the INTERLACED
1286a04a6428SPatrick 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.
12876fc41876SBarry Smith 
1288005d9f20SPatrick Sanan    The telescoping preconditioner is aware of nullspaces and near nullspaces which are attached to the B operator.
12898439623fSPatrick Sanan    In the case where B has a (near) nullspace attached, the (near) nullspace vectors are extracted from B and mapped into
1290005d9f20SPatrick Sanan    a new (near) nullspace, defined on the sub-communicator, which is attached to B' (the B operator which was scattered to c')
12916fc41876SBarry Smith 
129200fea0ebSDave May    The telescoping preconditioner can re-partition an attached DM if it is a DMDA (2D or 3D -
12934c500f23SPierre Jolivet    support for 1D DMDAs is not provided). If a DMDA is found, a topologically equivalent DMDA is created on c'
129400fea0ebSDave May    and this new DM is attached the sub KSP. The design of telescope is such that it should be possible to extend support
12958439623fSPatrick Sanan    for re-partitioning other to DM's (e.g. DMPLEX). The user can supply a flag to ignore attached DMs.
129600fea0ebSDave May    Alternatively, user-provided re-partitioned DMs can be used via -pc_telescope_use_coarse_dm.
12976fc41876SBarry Smith 
129800fea0ebSDave May    With the default setup mode, B' is defined by fusing rows (in order) associated with MPI ranks common to c and c'.
12996fc41876SBarry Smith 
13008439623fSPatrick Sanan    When a DMDA is attached to the parent preconditioner, B' is defined by: (i) performing a symmetric permutation of B
13017dae84e0SHong Zhang    into the ordering defined by the DMDA on c', (ii) extracting the local chunks via MatCreateSubMatrices(), (iii) fusing the
13026fc41876SBarry Smith    locally (sequential) matrices defined on the ranks common to c and c' into B' using MatCreateMPIMatConcatenateSeqMat()
13036fc41876SBarry Smith 
13048439623fSPatrick Sanan    Limitations/improvements include the following.
13058439623fSPatrick Sanan    VecPlaceArray() could be used within PCApply() to improve efficiency and reduce memory usage.
130600fea0ebSDave May    A unified mechanism to query for user contexts as required by KSPSetComputeOperators() and MatNullSpaceSetFunction().
13076fc41876SBarry Smith 
13080705ae88SPierre Jolivet    The symmetric permutation used when a DMDA is encountered is performed via explicitly assembling a permutation matrix P,
13098439623fSPatrick 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
13100705ae88SPierre Jolivet    VecPermute() does not support the use case required here. By computing P, one can permute both the operator and RHS in a
13116fc41876SBarry Smith    consistent manner.
13126fc41876SBarry Smith 
131300fea0ebSDave May    Mapping of vectors (default setup mode) is performed in the following way.
131400fea0ebSDave 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.
13158439623fSPatrick Sanan    Using the interlaced creation routine, the ranks in c with color = 0 will be rank 0 and 2.
131600fea0ebSDave May    We perform the scatter to the sub-communicator in the following way.
1317514db83aSDave May    [1] Given a vector x defined on communicator c
13186fc41876SBarry Smith 
1319514db83aSDave May .vb
1320514db83aSDave May    rank(c)  local values of x
1321514db83aSDave May    ------- ----------------------------------------
1322514db83aSDave May         0   [  0.0,  1.0,  2.0,  3.0,  4.0,  5.0 ]
1323514db83aSDave May         1   [  6.0,  7.0,  8.0,  9.0, 10.0, 11.0 ]
1324514db83aSDave May         2   [ 12.0, 13.0, 14.0, 15.0, 16.0, 17.0 ]
1325514db83aSDave May         3   [ 18.0, 19.0, 20.0, 21.0, 22.0, 23.0 ]
1326514db83aSDave May .ve
13276fc41876SBarry Smith 
1328514db83aSDave May    scatter into xtmp defined also on comm c, so that we have the following values
13296fc41876SBarry Smith 
1330514db83aSDave May .vb
1331514db83aSDave May    rank(c)  local values of xtmp
1332514db83aSDave May    ------- ----------------------------------------------------------------------------
1333514db83aSDave 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 ]
1334514db83aSDave May         1   [ ]
1335514db83aSDave 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 ]
1336514db83aSDave May         3   [ ]
1337514db83aSDave May .ve
13386fc41876SBarry Smith 
13396fc41876SBarry Smith    The entries on rank 1 and 3 (ranks which do not have a color = 0 in c') have no values
13406fc41876SBarry Smith 
1341514db83aSDave 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'.
13426fc41876SBarry Smith    Ranks 0 and 2 are the only ranks in the subcomm which have a color = 0.
13436fc41876SBarry Smith 
1344514db83aSDave May .vb
1345514db83aSDave May    rank(c')  local values of xred
1346514db83aSDave May    -------- ----------------------------------------------------------------------------
1347514db83aSDave 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 ]
1348514db83aSDave 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 ]
1349514db83aSDave May .ve
13501e07b27eSBarry Smith 
13511e07b27eSBarry Smith   Contributed by Dave May
13521e07b27eSBarry Smith 
1353bf00f589SPatrick Sanan   Reference:
1354bf00f589SPatrick 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
1355bf00f589SPatrick Sanan 
1356db781477SPatrick Sanan .seealso: `PCTelescopeGetKSP()`, `PCTelescopeGetDM()`, `PCTelescopeGetReductionFactor()`, `PCTelescopeSetReductionFactor()`, `PCTelescopeGetIgnoreDM()`, `PCTelescopeSetIgnoreDM()`, `PCREDUNDANT`
13571e07b27eSBarry Smith M*/
13581e07b27eSBarry Smith PETSC_EXTERN PetscErrorCode PCCreate_Telescope(PC pc)
13591e07b27eSBarry Smith {
13601e07b27eSBarry Smith   struct _PC_Telescope *sred;
13611e07b27eSBarry Smith 
13621e07b27eSBarry Smith   PetscFunctionBegin;
13639566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(pc,&sred));
13642a22aa42SDave May   sred->psubcomm       = NULL;
136548a10b22SPatrick Sanan   sred->subcommtype    = PETSC_SUBCOMM_INTERLACED;
13662a22aa42SDave May   sred->subcomm        = MPI_COMM_NULL;
13671e07b27eSBarry Smith   sred->redfactor      = 1;
13681e07b27eSBarry Smith   sred->ignore_dm      = PETSC_FALSE;
13697c5279cbSDave May   sred->ignore_kspcomputeoperators = PETSC_FALSE;
13708d9f7141SDave May   sred->use_coarse_dm  = PETSC_FALSE;
13711e07b27eSBarry Smith   pc->data             = (void*)sred;
13721e07b27eSBarry Smith 
13731e07b27eSBarry Smith   pc->ops->apply           = PCApply_Telescope;
13741e07b27eSBarry Smith   pc->ops->applytranspose  = NULL;
1375f650675bSDave May   pc->ops->applyrichardson = PCApplyRichardson_Telescope;
13761e07b27eSBarry Smith   pc->ops->setup           = PCSetUp_Telescope;
13771e07b27eSBarry Smith   pc->ops->destroy         = PCDestroy_Telescope;
13781e07b27eSBarry Smith   pc->ops->reset           = PCReset_Telescope;
13791e07b27eSBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_Telescope;
13801e07b27eSBarry Smith   pc->ops->view            = PCView_Telescope;
13811e07b27eSBarry Smith 
13821e07b27eSBarry Smith   sred->pctelescope_setup_type              = PCTelescopeSetUp_default;
13831e07b27eSBarry Smith   sred->pctelescope_matcreate_type          = PCTelescopeMatCreate_default;
13841e07b27eSBarry Smith   sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_default;
13851e07b27eSBarry Smith   sred->pctelescope_reset_type              = NULL;
13861e07b27eSBarry Smith 
13879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetKSP_C",PCTelescopeGetKSP_Telescope));
13889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetSubcommType_C",PCTelescopeGetSubcommType_Telescope));
13899566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetSubcommType_C",PCTelescopeSetSubcommType_Telescope));
13909566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetReductionFactor_C",PCTelescopeGetReductionFactor_Telescope));
13919566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetReductionFactor_C",PCTelescopeSetReductionFactor_Telescope));
13929566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetIgnoreDM_C",PCTelescopeGetIgnoreDM_Telescope));
13939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetIgnoreDM_C",PCTelescopeSetIgnoreDM_Telescope));
13949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetIgnoreKSPComputeOperators_C",PCTelescopeGetIgnoreKSPComputeOperators_Telescope));
13959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetIgnoreKSPComputeOperators_C",PCTelescopeSetIgnoreKSPComputeOperators_Telescope));
13969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetDM_C",PCTelescopeGetDM_Telescope));
13979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetUseCoarseDM_C",PCTelescopeGetUseCoarseDM_Telescope));
13989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetUseCoarseDM_C",PCTelescopeSetUseCoarseDM_Telescope));
13991e07b27eSBarry Smith   PetscFunctionReturn(0);
14001e07b27eSBarry Smith }
1401