xref: /petsc/src/ksp/pc/impls/telescope/telescope.c (revision 6fc41876b0206b36851b9e44860541f31c3cd81b)
11e07b27eSBarry Smith 
21e07b27eSBarry Smith 
31e07b27eSBarry Smith 
4*6fc41876SBarry Smith #include <petsc/private/pcimpl.h>
51e07b27eSBarry Smith #include <petscksp.h> /*I "petscksp.h" I*/
61e07b27eSBarry Smith #include <petscdm.h> /*I "petscdm.h" I*/
71e07b27eSBarry Smith 
81e07b27eSBarry Smith #include "telescope.h"
91e07b27eSBarry Smith 
101e07b27eSBarry Smith /*
111e07b27eSBarry Smith  PCTelescopeSetUp_default()
121e07b27eSBarry Smith  PCTelescopeMatCreate_default()
131e07b27eSBarry Smith 
141e07b27eSBarry Smith  default
151e07b27eSBarry Smith 
161e07b27eSBarry Smith  // scatter in
171e07b27eSBarry Smith  x(comm) -> xtmp(comm)
181e07b27eSBarry Smith 
191e07b27eSBarry Smith  xred(subcomm) <- xtmp
201e07b27eSBarry Smith  yred(subcomm)
211e07b27eSBarry Smith 
221e07b27eSBarry Smith  yred(subcomm) --> xtmp
231e07b27eSBarry Smith 
241e07b27eSBarry Smith  // scatter out
251e07b27eSBarry Smith  xtmp(comm) -> y(comm)
261e07b27eSBarry Smith */
271e07b27eSBarry Smith 
281e07b27eSBarry Smith PetscBool isActiveRank(PetscSubcomm scomm)
291e07b27eSBarry Smith {
301e07b27eSBarry Smith   if (scomm->color == 0) { return PETSC_TRUE; }
311e07b27eSBarry Smith   else { return PETSC_FALSE; }
321e07b27eSBarry Smith }
331e07b27eSBarry Smith 
341e07b27eSBarry Smith #undef __FUNCT__
351e07b27eSBarry Smith #define __FUNCT__ "private_PCTelescopeGetSubDM"
361e07b27eSBarry Smith DM private_PCTelescopeGetSubDM(PC_Telescope sred)
371e07b27eSBarry Smith {
38c6a0d831SBarry Smith   DM subdm = NULL;
391e07b27eSBarry Smith 
401e07b27eSBarry Smith   if (!isActiveRank(sred->psubcomm)) { subdm = NULL; }
411e07b27eSBarry Smith   else {
421e07b27eSBarry Smith     switch (sred->sr_type) {
431e07b27eSBarry Smith     case TELESCOPE_DEFAULT: subdm = NULL;
441e07b27eSBarry Smith       break;
451e07b27eSBarry Smith     case TELESCOPE_DMDA:    subdm = ((PC_Telescope_DMDACtx*)sred->dm_ctx)->dmrepart;
461e07b27eSBarry Smith       break;
471e07b27eSBarry Smith     case TELESCOPE_DMPLEX:  subdm = NULL;
481e07b27eSBarry Smith       break;
491e07b27eSBarry Smith     }
501e07b27eSBarry Smith   }
511e07b27eSBarry Smith   return(subdm);
521e07b27eSBarry Smith }
531e07b27eSBarry Smith 
541e07b27eSBarry Smith #undef __FUNCT__
551e07b27eSBarry Smith #define __FUNCT__ "PCTelescopeSetUp_default"
561e07b27eSBarry Smith PetscErrorCode PCTelescopeSetUp_default(PC pc,PC_Telescope sred)
571e07b27eSBarry Smith {
581e07b27eSBarry Smith   PetscErrorCode ierr;
591e07b27eSBarry Smith   PetscInt       m,M,bs,st,ed;
601e07b27eSBarry Smith   Vec            x,xred,yred,xtmp;
611e07b27eSBarry Smith   Mat            B;
621e07b27eSBarry Smith   MPI_Comm       comm,subcomm;
631e07b27eSBarry Smith   VecScatter     scatter;
641e07b27eSBarry Smith   IS             isin;
651e07b27eSBarry Smith 
661e07b27eSBarry Smith   PetscFunctionBegin;
671e07b27eSBarry Smith   ierr = PetscInfo(pc,"PCTelescope: setup (default)\n");CHKERRQ(ierr);
681e07b27eSBarry Smith   comm = PetscSubcommParent(sred->psubcomm);
691e07b27eSBarry Smith   subcomm = PetscSubcommChild(sred->psubcomm);
701e07b27eSBarry Smith 
711e07b27eSBarry Smith   ierr = PCGetOperators(pc,NULL,&B);CHKERRQ(ierr);
721e07b27eSBarry Smith   ierr = MatGetSize(B,&M,NULL);CHKERRQ(ierr);
731e07b27eSBarry Smith   ierr = MatGetBlockSize(B,&bs);CHKERRQ(ierr);
741e07b27eSBarry Smith   ierr = MatCreateVecs(B,&x,NULL);CHKERRQ(ierr);
751e07b27eSBarry Smith 
761e07b27eSBarry Smith   xred = NULL;
773ac26c5eSBarry Smith   m    = 0;
781e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
791e07b27eSBarry Smith     ierr = VecCreate(subcomm,&xred);CHKERRQ(ierr);
801e07b27eSBarry Smith     ierr = VecSetSizes(xred,PETSC_DECIDE,M);CHKERRQ(ierr);
811e07b27eSBarry Smith     ierr = VecSetBlockSize(xred,bs);CHKERRQ(ierr);
821e07b27eSBarry Smith     ierr = VecSetFromOptions(xred);CHKERRQ(ierr);
831e07b27eSBarry Smith     ierr = VecGetLocalSize(xred,&m);
841e07b27eSBarry Smith   }
851e07b27eSBarry Smith 
861e07b27eSBarry Smith   yred = NULL;
871e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
881e07b27eSBarry Smith     ierr = VecDuplicate(xred,&yred);CHKERRQ(ierr);
891e07b27eSBarry Smith   }
901e07b27eSBarry Smith 
911e07b27eSBarry Smith   ierr = VecCreate(comm,&xtmp);CHKERRQ(ierr);
921e07b27eSBarry Smith   ierr = VecSetSizes(xtmp,m,PETSC_DECIDE);CHKERRQ(ierr);
931e07b27eSBarry Smith   ierr = VecSetBlockSize(xtmp,bs);CHKERRQ(ierr);
941e07b27eSBarry Smith   ierr = VecSetType(xtmp,((PetscObject)x)->type_name);CHKERRQ(ierr);
951e07b27eSBarry Smith 
961e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
971e07b27eSBarry Smith     ierr = VecGetOwnershipRange(xred,&st,&ed);CHKERRQ(ierr);
981e07b27eSBarry Smith     ierr = ISCreateStride(comm,(ed-st),st,1,&isin);CHKERRQ(ierr);
991e07b27eSBarry Smith   } else {
1001e07b27eSBarry Smith     ierr = VecGetOwnershipRange(x,&st,&ed);CHKERRQ(ierr);
1013ac26c5eSBarry Smith     ierr = ISCreateStride(comm,0,st,1,&isin);CHKERRQ(ierr);
1021e07b27eSBarry Smith   }
1031e07b27eSBarry Smith   ierr = ISSetBlockSize(isin,bs);CHKERRQ(ierr);
1041e07b27eSBarry Smith 
1051e07b27eSBarry Smith   ierr = VecScatterCreate(x,isin,xtmp,NULL,&scatter);CHKERRQ(ierr);
1061e07b27eSBarry Smith 
1071e07b27eSBarry Smith   sred->isin    = isin;
1081e07b27eSBarry Smith   sred->scatter = scatter;
1091e07b27eSBarry Smith   sred->xred    = xred;
1101e07b27eSBarry Smith   sred->yred    = yred;
1111e07b27eSBarry Smith   sred->xtmp    = xtmp;
1121e07b27eSBarry Smith   ierr = VecDestroy(&x);CHKERRQ(ierr);
1131e07b27eSBarry Smith   PetscFunctionReturn(0);
1141e07b27eSBarry Smith }
1151e07b27eSBarry Smith 
1161e07b27eSBarry Smith #undef __FUNCT__
1171e07b27eSBarry Smith #define __FUNCT__ "PCTelescopeMatCreate_default"
1181e07b27eSBarry Smith PetscErrorCode PCTelescopeMatCreate_default(PC pc,PC_Telescope sred,MatReuse reuse,Mat *A)
1191e07b27eSBarry Smith {
1201e07b27eSBarry Smith   PetscErrorCode ierr;
1211e07b27eSBarry Smith   MPI_Comm       comm,subcomm;
1221e07b27eSBarry Smith   Mat            Bred,B;
1231e07b27eSBarry Smith   PetscInt       nr,nc;
1241e07b27eSBarry Smith   IS             isrow,iscol;
1251e07b27eSBarry Smith   Mat            Blocal,*_Blocal;
1261e07b27eSBarry Smith 
1271e07b27eSBarry Smith   PetscFunctionBegin;
1281e07b27eSBarry Smith   ierr = PetscInfo(pc,"PCTelescope: updating the redundant preconditioned operator (default)\n");CHKERRQ(ierr);
1291e07b27eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
1301e07b27eSBarry Smith   subcomm = PetscSubcommChild(sred->psubcomm);
1311e07b27eSBarry Smith   ierr = PCGetOperators(pc,NULL,&B);CHKERRQ(ierr);
1321e07b27eSBarry Smith   ierr = MatGetSize(B,&nr,&nc);CHKERRQ(ierr);
1331e07b27eSBarry Smith   isrow = sred->isin;
1341e07b27eSBarry Smith   ierr = ISCreateStride(comm,nc,0,1,&iscol);CHKERRQ(ierr);
1351e07b27eSBarry Smith   ierr = MatGetSubMatrices(B,1,&isrow,&iscol,MAT_INITIAL_MATRIX,&_Blocal);CHKERRQ(ierr);
1361e07b27eSBarry Smith   Blocal = *_Blocal;
1371e07b27eSBarry Smith   ierr = PetscFree(_Blocal);CHKERRQ(ierr);
1381e07b27eSBarry Smith   Bred = NULL;
1391e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
1401e07b27eSBarry Smith     PetscInt mm;
1411e07b27eSBarry Smith 
1421e07b27eSBarry Smith     if (reuse != MAT_INITIAL_MATRIX) { Bred = *A; }
1431e07b27eSBarry Smith 
1441e07b27eSBarry Smith     ierr = MatGetSize(Blocal,&mm,NULL);CHKERRQ(ierr);
1451e07b27eSBarry Smith     ierr = MatCreateMPIMatConcatenateSeqMat(subcomm,Blocal,mm,reuse,&Bred);CHKERRQ(ierr);
1461e07b27eSBarry Smith   }
1471e07b27eSBarry Smith   *A = Bred;
1481e07b27eSBarry Smith   ierr = ISDestroy(&iscol);CHKERRQ(ierr);
1491e07b27eSBarry Smith   ierr = MatDestroy(&Blocal);CHKERRQ(ierr);
1501e07b27eSBarry Smith   PetscFunctionReturn(0);
1511e07b27eSBarry Smith }
1521e07b27eSBarry Smith 
1531e07b27eSBarry Smith #undef __FUNCT__
1541e07b27eSBarry Smith #define __FUNCT__ "PCTelescopeMatNullSpaceCreate_default"
1551e07b27eSBarry Smith PetscErrorCode PCTelescopeMatNullSpaceCreate_default(PC pc,PC_Telescope sred,Mat sub_mat)
1561e07b27eSBarry Smith {
1571e07b27eSBarry Smith   PetscErrorCode   ierr;
1581e07b27eSBarry Smith   MatNullSpace     nullspace,sub_nullspace;
1591e07b27eSBarry Smith   Mat              A,B;
1601e07b27eSBarry Smith   PetscBool        has_const;
1611e07b27eSBarry Smith   PetscInt         i,k,n;
1621e07b27eSBarry Smith   const Vec        *vecs;
1631e07b27eSBarry Smith   Vec              *sub_vecs;
1641e07b27eSBarry Smith   MPI_Comm         subcomm;
1651e07b27eSBarry Smith 
1661e07b27eSBarry Smith   PetscFunctionBegin;
1671e07b27eSBarry Smith   ierr = PCGetOperators(pc,&A,&B);CHKERRQ(ierr);
1681e07b27eSBarry Smith   ierr = MatGetNullSpace(B,&nullspace);CHKERRQ(ierr);
1691e07b27eSBarry Smith   if (!nullspace) return(0);
1701e07b27eSBarry Smith 
1711e07b27eSBarry Smith   ierr = PetscInfo(pc,"PCTelescope: generating nullspace (default)\n");CHKERRQ(ierr);
1721e07b27eSBarry Smith   subcomm = PetscSubcommChild(sred->psubcomm);
1731e07b27eSBarry Smith   ierr = MatNullSpaceGetVecs(nullspace,&has_const,&n,&vecs);CHKERRQ(ierr);
1741e07b27eSBarry Smith 
1751e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
176e3acf2f7SBarry Smith     if (n) {
177e3acf2f7SBarry Smith       ierr = VecDuplicateVecs(sred->xred,n,&sub_vecs);CHKERRQ(ierr);
1781e07b27eSBarry Smith     }
1791e07b27eSBarry Smith   }
1801e07b27eSBarry Smith 
1811e07b27eSBarry Smith   /* copy entries */
1821e07b27eSBarry Smith   for (k=0; k<n; k++) {
1831e07b27eSBarry Smith     const PetscScalar *x_array;
1841e07b27eSBarry Smith     PetscScalar       *LA_sub_vec;
1851e07b27eSBarry Smith     PetscInt          st,ed,bs;
1861e07b27eSBarry Smith 
1871e07b27eSBarry Smith     /* pull in vector x->xtmp */
1881e07b27eSBarry Smith     ierr = VecScatterBegin(sred->scatter,vecs[k],sred->xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1891e07b27eSBarry Smith     ierr = VecScatterEnd(sred->scatter,vecs[k],sred->xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1901e07b27eSBarry Smith     /* copy vector entires into xred */
1911e07b27eSBarry Smith     ierr = VecGetBlockSize(sred->xtmp,&bs);CHKERRQ(ierr);
1921e07b27eSBarry Smith     ierr = VecGetArrayRead(sred->xtmp,&x_array);CHKERRQ(ierr);
1931e07b27eSBarry Smith     if (sub_vecs[k]) {
1941e07b27eSBarry Smith       ierr = VecGetOwnershipRange(sub_vecs[k],&st,&ed);CHKERRQ(ierr);
1951e07b27eSBarry Smith       ierr = VecGetArray(sub_vecs[k],&LA_sub_vec);CHKERRQ(ierr);
1961e07b27eSBarry Smith       for (i=0; i<ed-st; i++) {
1971e07b27eSBarry Smith         LA_sub_vec[i] = x_array[i];
1981e07b27eSBarry Smith       }
1991e07b27eSBarry Smith       ierr = VecRestoreArray(sub_vecs[k],&LA_sub_vec);CHKERRQ(ierr);
2001e07b27eSBarry Smith     }
2011e07b27eSBarry Smith     ierr = VecRestoreArrayRead(sred->xtmp,&x_array);CHKERRQ(ierr);
2021e07b27eSBarry Smith   }
2031e07b27eSBarry Smith 
2041e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
2051e07b27eSBarry Smith     /* create new nullspace for redundant object */
2061e07b27eSBarry Smith     ierr = MatNullSpaceCreate(subcomm,has_const,n,sub_vecs,&sub_nullspace);CHKERRQ(ierr);
2071e07b27eSBarry Smith     /* attach redundant nullspace to Bred */
2081e07b27eSBarry Smith     ierr = MatSetNullSpace(sub_mat,sub_nullspace);CHKERRQ(ierr);
209e3acf2f7SBarry Smith     ierr = VecDestroyVecs(n,&sub_vecs);CHKERRQ(ierr);
2101e07b27eSBarry Smith   }
2111e07b27eSBarry Smith   PetscFunctionReturn(0);
2121e07b27eSBarry Smith }
2131e07b27eSBarry Smith 
2141e07b27eSBarry Smith #undef __FUNCT__
2151e07b27eSBarry Smith #define __FUNCT__ "PCView_Telescope"
2161e07b27eSBarry Smith static PetscErrorCode PCView_Telescope(PC pc,PetscViewer viewer)
2171e07b27eSBarry Smith {
2181e07b27eSBarry Smith   PC_Telescope     sred = (PC_Telescope)pc->data;
2191e07b27eSBarry Smith   PetscErrorCode   ierr;
2201e07b27eSBarry Smith   PetscBool        iascii,isstring;
2211e07b27eSBarry Smith   PetscViewer      subviewer;
2221e07b27eSBarry Smith 
2231e07b27eSBarry Smith   PetscFunctionBegin;
2241e07b27eSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
2251e07b27eSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr);
2261e07b27eSBarry Smith   if (iascii) {
2271e07b27eSBarry Smith     if (!sred->psubcomm) {
2281e07b27eSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Telescope: preconditioner not yet setup\n");CHKERRQ(ierr);
2291e07b27eSBarry Smith     } else {
2301e07b27eSBarry Smith       MPI_Comm    comm,subcomm;
2311e07b27eSBarry Smith       PetscMPIInt comm_size,subcomm_size;
2321e07b27eSBarry Smith       DM          dm,subdm;
2331e07b27eSBarry Smith 
2341e07b27eSBarry Smith       ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
2351e07b27eSBarry Smith       subdm = private_PCTelescopeGetSubDM(sred);
2361e07b27eSBarry Smith       comm = PetscSubcommParent(sred->psubcomm);
2371e07b27eSBarry Smith       subcomm = PetscSubcommChild(sred->psubcomm);
2381e07b27eSBarry Smith       ierr = MPI_Comm_size(comm,&comm_size);CHKERRQ(ierr);
2391e07b27eSBarry Smith       ierr = MPI_Comm_size(subcomm,&subcomm_size);CHKERRQ(ierr);
2401e07b27eSBarry Smith 
2411e07b27eSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Telescope: parent comm size reduction factor = %D\n",sred->redfactor);CHKERRQ(ierr);
2421e07b27eSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Telescope: comm_size = %d , subcomm_size = %d\n",(int)comm_size,(int)subcomm_size);CHKERRQ(ierr);
2431e07b27eSBarry Smith       ierr = PetscViewerGetSubViewer(viewer,subcomm,&subviewer);CHKERRQ(ierr);
2441e07b27eSBarry Smith       if (isActiveRank(sred->psubcomm)) {
2451e07b27eSBarry Smith         ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr);
2461e07b27eSBarry Smith 
2471e07b27eSBarry Smith         if (dm && sred->ignore_dm) {
2481e07b27eSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: ignoring DM\n");CHKERRQ(ierr);
2491e07b27eSBarry Smith         }
2501e07b27eSBarry Smith         switch (sred->sr_type) {
2511e07b27eSBarry Smith         case TELESCOPE_DEFAULT:
2521e07b27eSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: using default setup\n");CHKERRQ(ierr);
2531e07b27eSBarry Smith           break;
2541e07b27eSBarry Smith         case TELESCOPE_DMDA:
2551e07b27eSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: DMDA detected\n");CHKERRQ(ierr);
2561e07b27eSBarry Smith           ierr = DMView_DMDAShort(subdm,subviewer);CHKERRQ(ierr);
2571e07b27eSBarry Smith           break;
2581e07b27eSBarry Smith         case TELESCOPE_DMPLEX:
2591e07b27eSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: DMPLEX detected\n");CHKERRQ(ierr);
2601e07b27eSBarry Smith           break;
2611e07b27eSBarry Smith         }
2621e07b27eSBarry Smith 
2631e07b27eSBarry Smith         ierr = KSPView(sred->ksp,subviewer);CHKERRQ(ierr);
2641e07b27eSBarry Smith         ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr);
2651e07b27eSBarry Smith       }
2661e07b27eSBarry Smith       ierr = PetscViewerRestoreSubViewer(viewer,subcomm,&subviewer);CHKERRQ(ierr);
2671e07b27eSBarry Smith     }
2681e07b27eSBarry Smith   }
2691e07b27eSBarry Smith   PetscFunctionReturn(0);
2701e07b27eSBarry Smith }
2711e07b27eSBarry Smith 
2721e07b27eSBarry Smith #undef __FUNCT__
2731e07b27eSBarry Smith #define __FUNCT__ "PCSetUp_Telescope"
2741e07b27eSBarry Smith static PetscErrorCode PCSetUp_Telescope(PC pc)
2751e07b27eSBarry Smith {
2761e07b27eSBarry Smith   PC_Telescope      sred = (PC_Telescope)pc->data;
2771e07b27eSBarry Smith   PetscErrorCode    ierr;
278bd49479cSSatish Balay   MPI_Comm          comm,subcomm=0;
2791e07b27eSBarry Smith   PCTelescopeType   sr_type;
2801e07b27eSBarry Smith 
2811e07b27eSBarry Smith   PetscFunctionBegin;
2821e07b27eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
2831e07b27eSBarry Smith 
2841e07b27eSBarry Smith   /* subcomm definition */
2851e07b27eSBarry Smith   if (!pc->setupcalled) {
2861e07b27eSBarry Smith     if (!sred->psubcomm) {
2871e07b27eSBarry Smith       ierr = PetscSubcommCreate(comm,&sred->psubcomm);CHKERRQ(ierr);
2881e07b27eSBarry Smith       ierr = PetscSubcommSetNumber(sred->psubcomm,sred->redfactor);CHKERRQ(ierr);
2891e07b27eSBarry Smith       ierr = PetscSubcommSetType(sred->psubcomm,PETSC_SUBCOMM_INTERLACED);CHKERRQ(ierr);
2901e07b27eSBarry Smith       /* disable runtime switch of psubcomm type, e.g., '-psubcomm_type interlaced */
2911e07b27eSBarry Smith       /* ierr = PetscSubcommSetFromOptions(sred->psubcomm);CHKERRQ(ierr); */
2921e07b27eSBarry Smith       ierr = PetscLogObjectMemory((PetscObject)pc,sizeof(PetscSubcomm));CHKERRQ(ierr);
2931e07b27eSBarry Smith       /* create a new PC that processors in each subcomm have copy of */
2941e07b27eSBarry Smith     }
2951e07b27eSBarry Smith   }
2960f6f40a7SSatish Balay   subcomm = PetscSubcommChild(sred->psubcomm);
2971e07b27eSBarry Smith 
2981e07b27eSBarry Smith   /* internal KSP */
2991e07b27eSBarry Smith   if (!pc->setupcalled) {
3001e07b27eSBarry Smith     const char *prefix;
3011e07b27eSBarry Smith 
3021e07b27eSBarry Smith     if (isActiveRank(sred->psubcomm)) {
3031e07b27eSBarry Smith       ierr = KSPCreate(subcomm,&sred->ksp);CHKERRQ(ierr);
3041e07b27eSBarry Smith       ierr = KSPSetErrorIfNotConverged(sred->ksp,pc->erroriffailure);CHKERRQ(ierr);
3051e07b27eSBarry Smith       ierr = PetscObjectIncrementTabLevel((PetscObject)sred->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
3061e07b27eSBarry Smith       ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)sred->ksp);CHKERRQ(ierr);
3071e07b27eSBarry Smith       ierr = KSPSetType(sred->ksp,KSPPREONLY);CHKERRQ(ierr);
3081e07b27eSBarry Smith       ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
3091e07b27eSBarry Smith       ierr = KSPSetOptionsPrefix(sred->ksp,prefix);CHKERRQ(ierr);
3101e07b27eSBarry Smith       ierr = KSPAppendOptionsPrefix(sred->ksp,"telescope_");CHKERRQ(ierr);
3111e07b27eSBarry Smith     }
3121e07b27eSBarry Smith   }
3131e07b27eSBarry Smith   /* Determine type of setup/update */
3141e07b27eSBarry Smith   if (!pc->setupcalled) {
3151e07b27eSBarry Smith     PetscBool has_dm,same;
3161e07b27eSBarry Smith     DM        dm;
3171e07b27eSBarry Smith 
3181e07b27eSBarry Smith     sr_type = TELESCOPE_DEFAULT;
3191e07b27eSBarry Smith     has_dm = PETSC_FALSE;
3201e07b27eSBarry Smith     ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
3211e07b27eSBarry Smith     if (dm) { has_dm = PETSC_TRUE; }
3221e07b27eSBarry Smith     if (has_dm) {
3231e07b27eSBarry Smith       /* check for dmda */
3241e07b27eSBarry Smith       ierr = PetscObjectTypeCompare((PetscObject)dm,DMDA,&same);CHKERRQ(ierr);
3251e07b27eSBarry Smith       if (same) {
3261e07b27eSBarry Smith         ierr = PetscInfo(pc,"PCTelescope: found DMDA\n");CHKERRQ(ierr);
3271e07b27eSBarry Smith         sr_type = TELESCOPE_DMDA;
3281e07b27eSBarry Smith       }
3291e07b27eSBarry Smith       /* check for dmplex */
3301e07b27eSBarry Smith       ierr = PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&same);CHKERRQ(ierr);
3311e07b27eSBarry Smith       if (same) {
3321e07b27eSBarry Smith         PetscInfo(pc,"PCTelescope: found DMPLEX\n");
3331e07b27eSBarry Smith         sr_type = TELESCOPE_DMPLEX;
3341e07b27eSBarry Smith       }
3351e07b27eSBarry Smith     }
3361e07b27eSBarry Smith 
3371e07b27eSBarry Smith     if (sred->ignore_dm) {
3381e07b27eSBarry Smith       PetscInfo(pc,"PCTelescope: ignore DM\n");
3391e07b27eSBarry Smith       sr_type = TELESCOPE_DEFAULT;
3401e07b27eSBarry Smith     }
3411e07b27eSBarry Smith     sred->sr_type = sr_type;
3421e07b27eSBarry Smith   } else {
3431e07b27eSBarry Smith     sr_type = sred->sr_type;
3441e07b27eSBarry Smith   }
3451e07b27eSBarry Smith 
3461e07b27eSBarry Smith   /* set function pointers for repartition setup, matrix creation/update, matrix nullspace and reset functionality */
3471e07b27eSBarry Smith   switch (sr_type) {
3481e07b27eSBarry Smith   case TELESCOPE_DEFAULT:
3491e07b27eSBarry Smith     sred->pctelescope_setup_type              = PCTelescopeSetUp_default;
3501e07b27eSBarry Smith     sred->pctelescope_matcreate_type          = PCTelescopeMatCreate_default;
3511e07b27eSBarry Smith     sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_default;
3521e07b27eSBarry Smith     sred->pctelescope_reset_type              = NULL;
3531e07b27eSBarry Smith     break;
3541e07b27eSBarry Smith   case TELESCOPE_DMDA:
3551e07b27eSBarry Smith     pc->ops->apply                          = PCApply_Telescope_dmda;
3561e07b27eSBarry Smith     sred->pctelescope_setup_type              = PCTelescopeSetUp_dmda;
3571e07b27eSBarry Smith     sred->pctelescope_matcreate_type          = PCTelescopeMatCreate_dmda;
3581e07b27eSBarry Smith     sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_dmda;
3591e07b27eSBarry Smith     sred->pctelescope_reset_type              = PCReset_Telescope_dmda;
3601e07b27eSBarry Smith     break;
3611e07b27eSBarry Smith   case TELESCOPE_DMPLEX: SETERRQ(comm,PETSC_ERR_SUP,"Supprt for DMPLEX is currently not available");
3621e07b27eSBarry Smith     break;
3631e07b27eSBarry Smith   default: SETERRQ(comm,PETSC_ERR_SUP,"Only supprt for repartitioning DMDA is provided");
3641e07b27eSBarry Smith     break;
3651e07b27eSBarry Smith   }
3661e07b27eSBarry Smith 
3671e07b27eSBarry Smith   /* setup */
3681e07b27eSBarry Smith   if (sred->pctelescope_setup_type) {
3691e07b27eSBarry Smith     ierr = sred->pctelescope_setup_type(pc,sred);CHKERRQ(ierr);
3701e07b27eSBarry Smith   }
3711e07b27eSBarry Smith   /* update */
3721e07b27eSBarry Smith   if (!pc->setupcalled) {
3731e07b27eSBarry Smith     if (sred->pctelescope_matcreate_type) {
3741e07b27eSBarry Smith       ierr = sred->pctelescope_matcreate_type(pc,sred,MAT_INITIAL_MATRIX,&sred->Bred);CHKERRQ(ierr);
3751e07b27eSBarry Smith     }
3761e07b27eSBarry Smith     if (sred->pctelescope_matnullspacecreate_type) {
3771e07b27eSBarry Smith       ierr = sred->pctelescope_matnullspacecreate_type(pc,sred,sred->Bred);CHKERRQ(ierr);
3781e07b27eSBarry Smith     }
3791e07b27eSBarry Smith   } else {
3801e07b27eSBarry Smith     if (sred->pctelescope_matcreate_type) {
3811e07b27eSBarry Smith       ierr = sred->pctelescope_matcreate_type(pc,sred,MAT_REUSE_MATRIX,&sred->Bred);CHKERRQ(ierr);
3821e07b27eSBarry Smith     }
3831e07b27eSBarry Smith   }
3841e07b27eSBarry Smith 
3851e07b27eSBarry Smith   /* common - no construction */
3861e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
3871e07b27eSBarry Smith     ierr = KSPSetOperators(sred->ksp,sred->Bred,sred->Bred);CHKERRQ(ierr);
3881e07b27eSBarry Smith     if (pc->setfromoptionscalled && !pc->setupcalled){
3891e07b27eSBarry Smith       ierr = KSPSetFromOptions(sred->ksp);CHKERRQ(ierr);
3901e07b27eSBarry Smith     }
3911e07b27eSBarry Smith   }
3921e07b27eSBarry Smith   PetscFunctionReturn(0);
3931e07b27eSBarry Smith }
3941e07b27eSBarry Smith 
3951e07b27eSBarry Smith #undef __FUNCT__
3961e07b27eSBarry Smith #define __FUNCT__ "PCApply_Telescope"
3971e07b27eSBarry Smith static PetscErrorCode PCApply_Telescope(PC pc,Vec x,Vec y)
3981e07b27eSBarry Smith {
3991e07b27eSBarry Smith   PC_Telescope      sred = (PC_Telescope)pc->data;
4001e07b27eSBarry Smith   PetscErrorCode    ierr;
4011e07b27eSBarry Smith   Vec               xtmp,xred,yred;
4021e07b27eSBarry Smith   PetscInt          i,st,ed,bs;
4031e07b27eSBarry Smith   VecScatter        scatter;
4041e07b27eSBarry Smith   PetscScalar       *array;
4051e07b27eSBarry Smith   const PetscScalar *x_array;
4061e07b27eSBarry Smith 
4071e07b27eSBarry Smith   PetscFunctionBegin;
4081e07b27eSBarry Smith   xtmp    = sred->xtmp;
4091e07b27eSBarry Smith   scatter = sred->scatter;
4101e07b27eSBarry Smith   xred    = sred->xred;
4111e07b27eSBarry Smith   yred    = sred->yred;
4121e07b27eSBarry Smith 
4131e07b27eSBarry Smith   /* pull in vector x->xtmp */
4141e07b27eSBarry Smith   ierr = VecScatterBegin(scatter,x,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4151e07b27eSBarry Smith   ierr = VecScatterEnd(scatter,x,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4161e07b27eSBarry Smith 
4171e07b27eSBarry Smith   /* copy vector entires into xred */
4181e07b27eSBarry Smith   ierr = VecGetBlockSize(xtmp,&bs);CHKERRQ(ierr);
4191e07b27eSBarry Smith   ierr = VecGetArrayRead(xtmp,&x_array);CHKERRQ(ierr);
4201e07b27eSBarry Smith   if (xred) {
4211e07b27eSBarry Smith     PetscScalar *LA_xred;
4221e07b27eSBarry Smith     ierr = VecGetOwnershipRange(xred,&st,&ed);CHKERRQ(ierr);
4231e07b27eSBarry Smith     ierr = VecGetArray(xred,&LA_xred);CHKERRQ(ierr);
4241e07b27eSBarry Smith     for (i=0; i<ed-st; i++) {
4251e07b27eSBarry Smith       LA_xred[i] = x_array[i];
4261e07b27eSBarry Smith     }
4271e07b27eSBarry Smith     ierr = VecRestoreArray(xred,&LA_xred);CHKERRQ(ierr);
4281e07b27eSBarry Smith   }
4291e07b27eSBarry Smith   ierr = VecRestoreArrayRead(xtmp,&x_array);CHKERRQ(ierr);
4301e07b27eSBarry Smith   /* solve */
4311e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
4321e07b27eSBarry Smith     ierr = KSPSolve(sred->ksp,xred,yred);CHKERRQ(ierr);
4331e07b27eSBarry Smith   }
4341e07b27eSBarry Smith   /* return vector */
4351e07b27eSBarry Smith   ierr = VecGetBlockSize(xtmp,&bs);CHKERRQ(ierr);
4361e07b27eSBarry Smith   ierr = VecGetArray(xtmp,&array);CHKERRQ(ierr);
4371e07b27eSBarry Smith   if (yred) {
4381e07b27eSBarry Smith     const PetscScalar *LA_yred;
4391e07b27eSBarry Smith     ierr = VecGetOwnershipRange(yred,&st,&ed);CHKERRQ(ierr);
4401e07b27eSBarry Smith     ierr = VecGetArrayRead(yred,&LA_yred);CHKERRQ(ierr);
4411e07b27eSBarry Smith     for (i=0; i<ed-st; i++) {
4421e07b27eSBarry Smith       array[i] = LA_yred[i];
4431e07b27eSBarry Smith     }
4441e07b27eSBarry Smith     ierr = VecRestoreArrayRead(yred,&LA_yred);CHKERRQ(ierr);
4451e07b27eSBarry Smith   }
4461e07b27eSBarry Smith   ierr = VecRestoreArray(xtmp,&array);CHKERRQ(ierr);
4471e07b27eSBarry Smith   ierr = VecScatterBegin(scatter,xtmp,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4481e07b27eSBarry Smith   ierr = VecScatterEnd(scatter,xtmp,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4491e07b27eSBarry Smith   PetscFunctionReturn(0);
4501e07b27eSBarry Smith }
4511e07b27eSBarry Smith 
4521e07b27eSBarry Smith #undef __FUNCT__
4531e07b27eSBarry Smith #define __FUNCT__ "PCReset_Telescope"
4541e07b27eSBarry Smith static PetscErrorCode PCReset_Telescope(PC pc)
4551e07b27eSBarry Smith {
4561e07b27eSBarry Smith   PC_Telescope   sred = (PC_Telescope)pc->data;
4571e07b27eSBarry Smith   PetscErrorCode ierr;
4581e07b27eSBarry Smith 
4591e07b27eSBarry Smith   ierr = ISDestroy(&sred->isin);CHKERRQ(ierr);
4601e07b27eSBarry Smith   ierr = VecScatterDestroy(&sred->scatter);CHKERRQ(ierr);
461e3acf2f7SBarry Smith   ierr = VecDestroy(&sred->xred);CHKERRQ(ierr);
462e3acf2f7SBarry Smith   ierr = VecDestroy(&sred->yred);CHKERRQ(ierr);
463e3acf2f7SBarry Smith   ierr = VecDestroy(&sred->xtmp);CHKERRQ(ierr);
464e3acf2f7SBarry Smith   ierr = MatDestroy(&sred->Bred);CHKERRQ(ierr);
465e3acf2f7SBarry Smith   ierr = KSPReset(sred->ksp);CHKERRQ(ierr);
4661e07b27eSBarry Smith   if (sred->pctelescope_reset_type) {
4671e07b27eSBarry Smith     ierr = sred->pctelescope_reset_type(pc);CHKERRQ(ierr);
4681e07b27eSBarry Smith   }
4691e07b27eSBarry Smith   PetscFunctionReturn(0);
4701e07b27eSBarry Smith }
4711e07b27eSBarry Smith 
4721e07b27eSBarry Smith #undef __FUNCT__
4731e07b27eSBarry Smith #define __FUNCT__ "PCDestroy_Telescope"
4741e07b27eSBarry Smith static PetscErrorCode PCDestroy_Telescope(PC pc)
4751e07b27eSBarry Smith {
4761e07b27eSBarry Smith   PC_Telescope     sred = (PC_Telescope)pc->data;
4771e07b27eSBarry Smith   PetscErrorCode   ierr;
4781e07b27eSBarry Smith 
4791e07b27eSBarry Smith   PetscFunctionBegin;
4801e07b27eSBarry Smith   ierr = PCReset_Telescope(pc);CHKERRQ(ierr);
481e3acf2f7SBarry Smith   ierr = KSPDestroy(&sred->ksp);CHKERRQ(ierr);
4821e07b27eSBarry Smith   ierr = PetscSubcommDestroy(&sred->psubcomm);CHKERRQ(ierr);
483e3acf2f7SBarry Smith   ierr = PetscFree(sred->dm_ctx);CHKERRQ(ierr);
484e3acf2f7SBarry Smith   ierr = PetscFree(pc->data);CHKERRQ(ierr);
4851e07b27eSBarry Smith   PetscFunctionReturn(0);
4861e07b27eSBarry Smith }
4871e07b27eSBarry Smith 
4881e07b27eSBarry Smith #undef __FUNCT__
4891e07b27eSBarry Smith #define __FUNCT__ "PCSetFromOptions_Telescope"
4901e07b27eSBarry Smith static PetscErrorCode PCSetFromOptions_Telescope(PetscOptions *PetscOptionsObject,PC pc)
4911e07b27eSBarry Smith {
4921e07b27eSBarry Smith   PC_Telescope     sred = (PC_Telescope)pc->data;
4931e07b27eSBarry Smith   PetscErrorCode   ierr;
4941e07b27eSBarry Smith   MPI_Comm         comm;
4951e07b27eSBarry Smith   PetscMPIInt      size;
4961e07b27eSBarry Smith 
4971e07b27eSBarry Smith   PetscFunctionBegin;
4981e07b27eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
4991e07b27eSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
5001e07b27eSBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"Telescope options");CHKERRQ(ierr);
5011e07b27eSBarry Smith   ierr = PetscOptionsInt("-pc_telescope_reduction_factor","Factor to reduce comm size by","PCTelescopeSetReductionFactor",sred->redfactor,&sred->redfactor,0);CHKERRQ(ierr);
5021e07b27eSBarry Smith   if (sred->redfactor > size) SETERRQ(comm,PETSC_ERR_ARG_WRONG,"-pc_telescope_reduction_factor <= comm size");
5031e07b27eSBarry Smith   ierr = PetscOptionsBool("-pc_telescope_ignore_dm","Ignore any DM attached to the PC","PCTelescopeSetIgnoreDM",sred->ignore_dm,&sred->ignore_dm,0);CHKERRQ(ierr);
5041e07b27eSBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
5051e07b27eSBarry Smith   PetscFunctionReturn(0);
5061e07b27eSBarry Smith }
5071e07b27eSBarry Smith 
5081e07b27eSBarry Smith /* PC simplementation specific API's */
5091e07b27eSBarry Smith 
5101e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetKSP_Telescope(PC pc,KSP *ksp)
5111e07b27eSBarry Smith {
5121e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
513bd49479cSSatish Balay   PetscFunctionBegin;
5141e07b27eSBarry Smith   if (ksp) *ksp = red->ksp;
515bd49479cSSatish Balay   PetscFunctionReturn(0);
5161e07b27eSBarry Smith }
5171e07b27eSBarry Smith 
5181e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetReductionFactor_Telescope(PC pc,PetscInt *fact)
5191e07b27eSBarry Smith {
5201e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
521bd49479cSSatish Balay   PetscFunctionBegin;
5221e07b27eSBarry Smith   if (fact) *fact = red->redfactor;
523bd49479cSSatish Balay   PetscFunctionReturn(0);
5241e07b27eSBarry Smith }
5251e07b27eSBarry Smith 
5261e07b27eSBarry Smith static PetscErrorCode PCTelescopeSetReductionFactor_Telescope(PC pc,PetscInt fact)
5271e07b27eSBarry Smith {
5281e07b27eSBarry Smith   PC_Telescope     red = (PC_Telescope)pc->data;
5291e07b27eSBarry Smith   PetscMPIInt      size;
5301e07b27eSBarry Smith   PetscErrorCode   ierr;
5311e07b27eSBarry Smith 
532bd49479cSSatish Balay   PetscFunctionBegin;
5331e07b27eSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
5341e07b27eSBarry Smith   if (fact <= 0) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Reduction factor of telescoping PC %D must be positive",fact);
5351e07b27eSBarry Smith   if (fact > size) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Reduction factor of telescoping PC %D must be <= comm.size",fact);
5361e07b27eSBarry Smith   red->redfactor = fact;
537bd49479cSSatish Balay   PetscFunctionReturn(0);
5381e07b27eSBarry Smith }
5391e07b27eSBarry Smith 
5401e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetIgnoreDM_Telescope(PC pc,PetscBool *v)
5411e07b27eSBarry Smith {
5421e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
543bd49479cSSatish Balay   PetscFunctionBegin;
5441e07b27eSBarry Smith   if (v) *v = red->ignore_dm;
545bd49479cSSatish Balay   PetscFunctionReturn(0);
5461e07b27eSBarry Smith }
5471e07b27eSBarry Smith static PetscErrorCode PCTelescopeSetIgnoreDM_Telescope(PC pc,PetscBool v)
5481e07b27eSBarry Smith {
5491e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
550bd49479cSSatish Balay   PetscFunctionBegin;
5511e07b27eSBarry Smith   red->ignore_dm = v;
552bd49479cSSatish Balay   PetscFunctionReturn(0);
5531e07b27eSBarry Smith }
5541e07b27eSBarry Smith 
5551e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetDM_Telescope(PC pc,DM *dm)
5561e07b27eSBarry Smith {
5571e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
558bd49479cSSatish Balay   PetscFunctionBegin;
5591e07b27eSBarry Smith   *dm = private_PCTelescopeGetSubDM(red);
560bd49479cSSatish Balay   PetscFunctionReturn(0);
5611e07b27eSBarry Smith }
5621e07b27eSBarry Smith 
5631e07b27eSBarry Smith /*@
5641e07b27eSBarry Smith  PCTelescopeGetKSP - Gets the KSP created by the telescoping PC.
5651e07b27eSBarry Smith 
5661e07b27eSBarry Smith  Not Collective
5671e07b27eSBarry Smith 
5681e07b27eSBarry Smith  Input Parameter:
5691e07b27eSBarry Smith  .  pc - the preconditioner context
5701e07b27eSBarry Smith 
5711e07b27eSBarry Smith  Output Parameter:
5721e07b27eSBarry Smith  .  subksp - the KSP defined the smaller set of processes
5731e07b27eSBarry Smith 
5741e07b27eSBarry Smith  Level: advanced
5751e07b27eSBarry Smith 
5761e07b27eSBarry Smith  .keywords: PC, telescopting solve
5771e07b27eSBarry Smith  @*/
5781e07b27eSBarry Smith PetscErrorCode PCTelescopeGetKSP(PC pc,KSP *subksp)
5791e07b27eSBarry Smith {
580bd49479cSSatish Balay   PetscErrorCode ierr;
581bd49479cSSatish Balay   PetscFunctionBegin;
582bd49479cSSatish Balay   ierr = PetscTryMethod(pc,"PCTelescopeGetKSP_C",(PC,KSP*),(pc,subksp));CHKERRQ(ierr);
583bd49479cSSatish Balay   PetscFunctionReturn(0);
5841e07b27eSBarry Smith }
5851e07b27eSBarry Smith 
5861e07b27eSBarry Smith /*@
5871e07b27eSBarry Smith  PCTelescopeGetReductionFactor - Gets the factor by which the original number of processes has been reduced by.
5881e07b27eSBarry Smith 
5891e07b27eSBarry Smith  Not Collective
5901e07b27eSBarry Smith 
5911e07b27eSBarry Smith  Input Parameter:
5921e07b27eSBarry Smith  .  pc - the preconditioner context
5931e07b27eSBarry Smith 
5941e07b27eSBarry Smith  Output Parameter:
5951e07b27eSBarry Smith  .  fact - the reduction factor
5961e07b27eSBarry Smith 
5971e07b27eSBarry Smith  Level: advanced
5981e07b27eSBarry Smith 
5991e07b27eSBarry Smith  .keywords: PC, telescoping solve
6001e07b27eSBarry Smith  @*/
6011e07b27eSBarry Smith PetscErrorCode PCTelescopeGetReductionFactor(PC pc,PetscInt *fact)
6021e07b27eSBarry Smith {
603bd49479cSSatish Balay   PetscErrorCode ierr;
604bd49479cSSatish Balay   PetscFunctionBegin;
605bd49479cSSatish Balay   ierr = PetscTryMethod(pc,"PCTelescopeGetReductionFactor_C",(PC,PetscInt*),(pc,fact));CHKERRQ(ierr);
606bd49479cSSatish Balay   PetscFunctionReturn(0);
6071e07b27eSBarry Smith }
6081e07b27eSBarry Smith 
6091e07b27eSBarry Smith /*@
6101e07b27eSBarry Smith  PCTelescopeSetReductionFactor - Sets the factor by which the original number of processes has been reduced by.
6111e07b27eSBarry Smith 
6121e07b27eSBarry Smith  Not Collective
6131e07b27eSBarry Smith 
6141e07b27eSBarry Smith  Input Parameter:
6151e07b27eSBarry Smith  .  pc - the preconditioner context
6161e07b27eSBarry Smith 
6171e07b27eSBarry Smith  Output Parameter:
6181e07b27eSBarry Smith  .  fact - the reduction factor
6191e07b27eSBarry Smith 
6201e07b27eSBarry Smith  Level: advanced
6211e07b27eSBarry Smith 
6221e07b27eSBarry Smith  .keywords: PC, telescoping solve
6231e07b27eSBarry Smith  @*/
6241e07b27eSBarry Smith PetscErrorCode PCTelescopeSetReductionFactor(PC pc,PetscInt fact)
6251e07b27eSBarry Smith {
626bd49479cSSatish Balay   PetscErrorCode ierr;
627bd49479cSSatish Balay   PetscFunctionBegin;
628bd49479cSSatish Balay   ierr = PetscTryMethod(pc,"PCTelescopeSetReductionFactor_C",(PC,PetscInt),(pc,fact));CHKERRQ(ierr);
629bd49479cSSatish Balay   PetscFunctionReturn(0);
6301e07b27eSBarry Smith }
6311e07b27eSBarry Smith 
6321e07b27eSBarry Smith /*@
6331e07b27eSBarry Smith  PCTelescopeGetIgnoreDM - Get the flag indicating if any DM attached to the PC will be used.
6341e07b27eSBarry Smith 
6351e07b27eSBarry Smith  Not Collective
6361e07b27eSBarry Smith 
6371e07b27eSBarry Smith  Input Parameter:
6381e07b27eSBarry Smith  .  pc - the preconditioner context
6391e07b27eSBarry Smith 
6401e07b27eSBarry Smith  Output Parameter:
6411e07b27eSBarry Smith  .  v - the flag
6421e07b27eSBarry Smith 
6431e07b27eSBarry Smith  Level: advanced
6441e07b27eSBarry Smith 
6451e07b27eSBarry Smith  .keywords: PC, telescoping solve
6461e07b27eSBarry Smith  @*/
6471e07b27eSBarry Smith PetscErrorCode PCTelescopeGetIgnoreDM(PC pc,PetscBool *v)
6481e07b27eSBarry Smith {
649bd49479cSSatish Balay   PetscErrorCode ierr;
650bd49479cSSatish Balay   PetscFunctionBegin;
651bd49479cSSatish Balay   ierr = PetscTryMethod(pc,"PCTelescopeGetIgnoreDM_C",(PC,PetscBool*),(pc,v));CHKERRQ(ierr);
652bd49479cSSatish Balay   PetscFunctionReturn(0);
6531e07b27eSBarry Smith }
6541e07b27eSBarry Smith 
6551e07b27eSBarry Smith /*@
6561e07b27eSBarry Smith  PCTelescopeSetIgnoreDM - Set a flag to ignore any DM attached to the PC.
6571e07b27eSBarry Smith 
6581e07b27eSBarry Smith  Not Collective
6591e07b27eSBarry Smith 
6601e07b27eSBarry Smith  Input Parameter:
6611e07b27eSBarry Smith  .  pc - the preconditioner context
6621e07b27eSBarry Smith 
6631e07b27eSBarry Smith  Output Parameter:
6641e07b27eSBarry Smith  .  v - Use PETSC_TRUE to ignore any DM
6651e07b27eSBarry Smith 
6661e07b27eSBarry Smith  Level: advanced
6671e07b27eSBarry Smith 
6681e07b27eSBarry Smith  .keywords: PC, telescoping solve
6691e07b27eSBarry Smith  @*/
670bfd6bcc6SSatish Balay PetscErrorCode PCTelescopeSetIgnoreDM(PC pc,PetscBool v)
6711e07b27eSBarry Smith {
672bd49479cSSatish Balay   PetscErrorCode ierr;
673bd49479cSSatish Balay   PetscFunctionBegin;
674bd49479cSSatish Balay   ierr = PetscTryMethod(pc,"PCTelescopeSetIgnoreDM_C",(PC,PetscBool),(pc,v));CHKERRQ(ierr);
675bd49479cSSatish Balay   PetscFunctionReturn(0);
6761e07b27eSBarry Smith }
6771e07b27eSBarry Smith 
6781e07b27eSBarry Smith /*@
6791e07b27eSBarry Smith  PCTelescopeGetDM - Get the re-partitioned DM attached to the sub KSP.
6801e07b27eSBarry Smith 
6811e07b27eSBarry Smith  Not Collective
6821e07b27eSBarry Smith 
6831e07b27eSBarry Smith  Input Parameter:
6841e07b27eSBarry Smith  .  pc - the preconditioner context
6851e07b27eSBarry Smith 
6861e07b27eSBarry Smith  Output Parameter:
6871e07b27eSBarry Smith  .  subdm - The re-partitioned DM
6881e07b27eSBarry Smith 
6891e07b27eSBarry Smith  Level: advanced
6901e07b27eSBarry Smith 
6911e07b27eSBarry Smith  .keywords: PC, telescoping solve
6921e07b27eSBarry Smith  @*/
6931e07b27eSBarry Smith PetscErrorCode PCTelescopeGetDM(PC pc,DM *subdm)
6941e07b27eSBarry Smith {
695bd49479cSSatish Balay   PetscErrorCode ierr;
696bd49479cSSatish Balay   PetscFunctionBegin;
697bd49479cSSatish Balay   ierr = PetscTryMethod(pc,"PCTelescopeGetDM_C",(PC,DM*),(pc,subdm));CHKERRQ(ierr);
698bd49479cSSatish Balay   PetscFunctionReturn(0);
6991e07b27eSBarry Smith }
7001e07b27eSBarry Smith 
7011e07b27eSBarry Smith /* -------------------------------------------------------------------------------------*/
7021e07b27eSBarry Smith /*MC
7031e07b27eSBarry Smith    PCTELESCOPE - Runs a KSP solver on a sub-group of processors. MPI processes not in the sub-communicator are idle during the solve.
7041e07b27eSBarry Smith 
7051e07b27eSBarry Smith    Options Database:
7061e07b27eSBarry Smith +  -pc_telescope_reduction_factor <n> - factor to use communicator size by, for example if you are using 64 MPI processes and
7071e07b27eSBarry Smith    use an n of 4, the new sub-communicator will be 4 defined with 64/4 processes
7081e07b27eSBarry Smith -  -pc_telescope_ignore_dm <false> - flag to indicate whether an attached DM should be ignored
7091e07b27eSBarry Smith 
7101e07b27eSBarry Smith    Level: advanced
7111e07b27eSBarry Smith 
7121e07b27eSBarry Smith    Notes:
713*6fc41876SBarry Smith    The preconditioner is deemed telescopic as it only calls KSPSolve() on a single
714*6fc41876SBarry Smith    sub-communicator in contrast with PCREDUNDANT which calls KSPSolve() on N sub-communicators.
715*6fc41876SBarry Smith    This means there will be MPI processes within c, which will be idle during the application of this preconditioner.
716*6fc41876SBarry Smith 
7171e07b27eSBarry Smith    The default KSP is PREONLY. If a DM is attached to the PC, it is re-partitioned on the sub-communicator.
7181e07b27eSBarry Smith    Both the B mat operator and the right hand side vector are permuted into the new DOF ordering defined by the re-partitioned DM.
7191e07b27eSBarry Smith    Currently only support for re-partitioning a DMDA is provided.
7201e07b27eSBarry Smith    Any nullspace attached to the original Bmat operator are extracted, re-partitioned and set on the repartitioned Bmat operator.
7211e07b27eSBarry Smith    KSPSetComputeOperators() is not propagated to the sub KSP.
7221e07b27eSBarry Smith    Currently there is no support for the flag -pc_use_amat
7231e07b27eSBarry Smith 
724*6fc41876SBarry Smith    Assuming that the parent preconditioner (PC) is defined on a communicator c, this implementation
725*6fc41876SBarry Smith    creates a child sub-communicator (c') containing less MPI processes than the original parent preconditioner (PC).
726*6fc41876SBarry Smith 
727*6fc41876SBarry Smith   Developer Notes:
728*6fc41876SBarry Smith    During PCSetup, the B operator is scattered onto c'.
729*6fc41876SBarry Smith    Within PCApply, the RHS vector (x) is scattered into a redundant vector, xred (defined on c').
730*6fc41876SBarry Smith    Then KSPSolve() is executed on the c' communicator.
731*6fc41876SBarry Smith 
732*6fc41876SBarry Smith    The communicator used within the telescoping preconditioner is defined by a PetscSubcomm using the INTERLACED
733*6fc41876SBarry Smith    creation routine. We run the sub KSP on only the ranks within the communicator which have a color equal to zero.
734*6fc41876SBarry Smith 
735*6fc41876SBarry Smith    The telescoping preconditioner is aware of nullspaces which are attached to the only B operator.
736*6fc41876SBarry Smith    In case where B has a n nullspace attached, these nullspaces vectors are extract from B and mapped into
737*6fc41876SBarry Smith    a new nullspace (defined on the sub-communicator) which is attached to B' (the B operator which was scattered to c')
738*6fc41876SBarry Smith 
739*6fc41876SBarry Smith    The telescoping preconditioner is aware of an attached DM. In the event that the DM is of type DMDA (2D or 3D -
740*6fc41876SBarry Smith    1D support for 1D DMDAs is not provided), a new DMDA is created on c' (e.g. it is re-partitioned), and this new DM
741*6fc41876SBarry Smith    is attached the sub KSPSolve(). The design of telescope is such that it should be possible to extend support
742*6fc41876SBarry Smith    for re-partitioning other DM's (e.g. DMPLEX). The user can supply a flag to ignore attached DMs.
743*6fc41876SBarry Smith 
744*6fc41876SBarry Smith    By default, B' is defined by simply fusing rows from different MPI processes
745*6fc41876SBarry Smith 
746*6fc41876SBarry Smith    When a DMDA is attached to the parent preconditioner, B' is defined by: (i) performing a symmetric permuting of B
747*6fc41876SBarry Smith    into the ordering defined by the DMDA on c', (ii) extracting the local chunks via MatGetSubMatrices(), (iii) fusing the
748*6fc41876SBarry Smith    locally (sequential) matrices defined on the ranks common to c and c' into B' using MatCreateMPIMatConcatenateSeqMat()
749*6fc41876SBarry Smith 
750*6fc41876SBarry Smith    Limitations/improvements
751*6fc41876SBarry Smith    VecPlaceArray could be used within PCApply() to improve efficiency and reduce memory usage.
752*6fc41876SBarry Smith 
753*6fc41876SBarry Smith    The symmetric permutation used when a DMDA is encountered is performed via explicitly assmbleming a permutation matrix P,
754*6fc41876SBarry Smith    and performing P^T.A.P. Possibly it might be more efficient to use MatPermute(). I opted to use P^T.A.P as it appears
755*6fc41876SBarry Smith    VecPermute() does not supported for the use case required here. By computing P, I can permute both the operator and RHS in a
756*6fc41876SBarry Smith    consistent manner.
757*6fc41876SBarry Smith 
758*6fc41876SBarry Smith    Mapping of vectors is performed this way
759*6fc41876SBarry Smith    Suppose the parent comm size was 4, and we set a reduction factor of 2, thus would give a comm size on c' of 2.
760*6fc41876SBarry Smith    Using the interlaced creation routine, the ranks in c with color = 0, will be rank 0 and 2.
761*6fc41876SBarry Smith    We perform the scatter to the sub-comm in the following way,
762*6fc41876SBarry Smith    [1] Given a vector x defined on comm c
763*6fc41876SBarry Smith 
764*6fc41876SBarry Smith    rank(c) : _________ 0 ______  ________ 1 _______  ________ 2 _____________ ___________ 3 __________
765*6fc41876SBarry Smith          x : [0, 1, 2, 3, 4, 5] [6, 7, 8, 9, 10, 11] [12, 13, 14, 15, 16, 17] [18, 19, 20, 21, 22, 23]
766*6fc41876SBarry Smith 
767*6fc41876SBarry Smith    scatter to xtmp defined also on comm c so that we have the following values
768*6fc41876SBarry Smith 
769*6fc41876SBarry Smith    rank(c) : ___________________ 0 ________________  _1_  ______________________ 2 _______________________  __3_
770*6fc41876SBarry Smith       xtmp : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] [  ] [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23] [  ]
771*6fc41876SBarry Smith 
772*6fc41876SBarry Smith    The entries on rank 1 and 3 (ranks which do not have a color = 0 in c') have no values
773*6fc41876SBarry Smith 
774*6fc41876SBarry Smith 
775*6fc41876SBarry Smith    [2] Copy the value from rank 0, 2 (indices with respect to comm c) into the vector xred which is defined on communicator c'.
776*6fc41876SBarry Smith    Ranks 0 and 2 are the only ranks in the subcomm which have a color = 0.
777*6fc41876SBarry Smith 
778*6fc41876SBarry Smith     rank(c') : ___________________ 0 _______________  ______________________ 1 _____________________
779*6fc41876SBarry Smith       xred : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]
780*6fc41876SBarry Smith 
7811e07b27eSBarry Smith 
7821e07b27eSBarry Smith   Contributed by Dave May
7831e07b27eSBarry Smith 
784*6fc41876SBarry Smith .seealso:  PCTelescopeGetKSP(), PCTelescopeGetDM(), PCTelescopeGetReductionFactor(), PCTelescopeSetReductionFactor(), PCTelescopeGetIgnoreDM(), PCTelescopeSetIgnoreDM(), PCREDUNDANT
7851e07b27eSBarry Smith M*/
7861e07b27eSBarry Smith #undef __FUNCT__
7871e07b27eSBarry Smith #define __FUNCT__ "PCCreate_Telescope"
7881e07b27eSBarry Smith PETSC_EXTERN PetscErrorCode PCCreate_Telescope(PC pc)
7891e07b27eSBarry Smith {
7901e07b27eSBarry Smith   PetscErrorCode       ierr;
7911e07b27eSBarry Smith   struct _PC_Telescope *sred;
7921e07b27eSBarry Smith 
7931e07b27eSBarry Smith   PetscFunctionBegin;
7941e07b27eSBarry Smith   ierr = PetscNewLog(pc,&sred);CHKERRQ(ierr);
7951e07b27eSBarry Smith   sred->redfactor      = 1;
7961e07b27eSBarry Smith   sred->ignore_dm      = PETSC_FALSE;
7971e07b27eSBarry Smith   pc->data             = (void*)sred;
7981e07b27eSBarry Smith 
7991e07b27eSBarry Smith   pc->ops->apply          = PCApply_Telescope;
8001e07b27eSBarry Smith   pc->ops->applytranspose = NULL;
8011e07b27eSBarry Smith   pc->ops->setup          = PCSetUp_Telescope;
8021e07b27eSBarry Smith   pc->ops->destroy        = PCDestroy_Telescope;
8031e07b27eSBarry Smith   pc->ops->reset          = PCReset_Telescope;
8041e07b27eSBarry Smith   pc->ops->setfromoptions = PCSetFromOptions_Telescope;
8051e07b27eSBarry Smith   pc->ops->view           = PCView_Telescope;
8061e07b27eSBarry Smith 
8071e07b27eSBarry Smith   sred->pctelescope_setup_type              = PCTelescopeSetUp_default;
8081e07b27eSBarry Smith   sred->pctelescope_matcreate_type          = PCTelescopeMatCreate_default;
8091e07b27eSBarry Smith   sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_default;
8101e07b27eSBarry Smith   sred->pctelescope_reset_type              = NULL;
8111e07b27eSBarry Smith 
8121e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetKSP_C",PCTelescopeGetKSP_Telescope);CHKERRQ(ierr);
8131e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetReductionFactor_C",PCTelescopeGetReductionFactor_Telescope);CHKERRQ(ierr);
8141e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetReductionFactor_C",PCTelescopeSetReductionFactor_Telescope);CHKERRQ(ierr);
8151e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetIgnoreDM_C",PCTelescopeGetIgnoreDM_Telescope);CHKERRQ(ierr);
8161e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetIgnoreDM_C",PCTelescopeSetIgnoreDM_Telescope);CHKERRQ(ierr);
8171e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetDM_C",PCTelescopeGetDM_Telescope);CHKERRQ(ierr);
8181e07b27eSBarry Smith   PetscFunctionReturn(0);
8191e07b27eSBarry Smith }
820