xref: /petsc/src/ksp/pc/impls/telescope/telescope.c (revision 7c5279cb8146e6e34e803ebad74aef778c3b0aaf)
11e07b27eSBarry Smith 
21e07b27eSBarry Smith 
31e07b27eSBarry Smith 
46fc41876SBarry 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         }
250*7c5279cbSDave May         if (sred->ignore_kspcomputeoperators) {
251*7c5279cbSDave May           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: ignoring KSPComputeOperators\n");CHKERRQ(ierr);
252*7c5279cbSDave May         }
2531e07b27eSBarry Smith         switch (sred->sr_type) {
2541e07b27eSBarry Smith         case TELESCOPE_DEFAULT:
2551e07b27eSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: using default setup\n");CHKERRQ(ierr);
2561e07b27eSBarry Smith           break;
2571e07b27eSBarry Smith         case TELESCOPE_DMDA:
2581e07b27eSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: DMDA detected\n");CHKERRQ(ierr);
2591e07b27eSBarry Smith           ierr = DMView_DMDAShort(subdm,subviewer);CHKERRQ(ierr);
2601e07b27eSBarry Smith           break;
2611e07b27eSBarry Smith         case TELESCOPE_DMPLEX:
2621e07b27eSBarry Smith           ierr = PetscViewerASCIIPrintf(subviewer,"  Telescope: DMPLEX detected\n");CHKERRQ(ierr);
2631e07b27eSBarry Smith           break;
2641e07b27eSBarry Smith         }
2651e07b27eSBarry Smith 
2661e07b27eSBarry Smith         ierr = KSPView(sred->ksp,subviewer);CHKERRQ(ierr);
2671e07b27eSBarry Smith         ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr);
2681e07b27eSBarry Smith       }
2691e07b27eSBarry Smith       ierr = PetscViewerRestoreSubViewer(viewer,subcomm,&subviewer);CHKERRQ(ierr);
2701e07b27eSBarry Smith     }
2711e07b27eSBarry Smith   }
2721e07b27eSBarry Smith   PetscFunctionReturn(0);
2731e07b27eSBarry Smith }
2741e07b27eSBarry Smith 
2751e07b27eSBarry Smith #undef __FUNCT__
2761e07b27eSBarry Smith #define __FUNCT__ "PCSetUp_Telescope"
2771e07b27eSBarry Smith static PetscErrorCode PCSetUp_Telescope(PC pc)
2781e07b27eSBarry Smith {
2791e07b27eSBarry Smith   PC_Telescope      sred = (PC_Telescope)pc->data;
2801e07b27eSBarry Smith   PetscErrorCode    ierr;
281bd49479cSSatish Balay   MPI_Comm          comm,subcomm=0;
2821e07b27eSBarry Smith   PCTelescopeType   sr_type;
2831e07b27eSBarry Smith 
2841e07b27eSBarry Smith   PetscFunctionBegin;
2851e07b27eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
2861e07b27eSBarry Smith 
2871e07b27eSBarry Smith   /* subcomm definition */
2881e07b27eSBarry Smith   if (!pc->setupcalled) {
2891e07b27eSBarry Smith     if (!sred->psubcomm) {
2901e07b27eSBarry Smith       ierr = PetscSubcommCreate(comm,&sred->psubcomm);CHKERRQ(ierr);
2911e07b27eSBarry Smith       ierr = PetscSubcommSetNumber(sred->psubcomm,sred->redfactor);CHKERRQ(ierr);
2921e07b27eSBarry Smith       ierr = PetscSubcommSetType(sred->psubcomm,PETSC_SUBCOMM_INTERLACED);CHKERRQ(ierr);
2931e07b27eSBarry Smith       /* disable runtime switch of psubcomm type, e.g., '-psubcomm_type interlaced */
2941e07b27eSBarry Smith       /* ierr = PetscSubcommSetFromOptions(sred->psubcomm);CHKERRQ(ierr); */
2951e07b27eSBarry Smith       ierr = PetscLogObjectMemory((PetscObject)pc,sizeof(PetscSubcomm));CHKERRQ(ierr);
2961e07b27eSBarry Smith       /* create a new PC that processors in each subcomm have copy of */
2971e07b27eSBarry Smith     }
2981e07b27eSBarry Smith   }
2990f6f40a7SSatish Balay   subcomm = PetscSubcommChild(sred->psubcomm);
3001e07b27eSBarry Smith 
3011e07b27eSBarry Smith   /* internal KSP */
3021e07b27eSBarry Smith   if (!pc->setupcalled) {
3031e07b27eSBarry Smith     const char *prefix;
3041e07b27eSBarry Smith 
3051e07b27eSBarry Smith     if (isActiveRank(sred->psubcomm)) {
3061e07b27eSBarry Smith       ierr = KSPCreate(subcomm,&sred->ksp);CHKERRQ(ierr);
3071e07b27eSBarry Smith       ierr = KSPSetErrorIfNotConverged(sred->ksp,pc->erroriffailure);CHKERRQ(ierr);
3081e07b27eSBarry Smith       ierr = PetscObjectIncrementTabLevel((PetscObject)sred->ksp,(PetscObject)pc,1);CHKERRQ(ierr);
3091e07b27eSBarry Smith       ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)sred->ksp);CHKERRQ(ierr);
3101e07b27eSBarry Smith       ierr = KSPSetType(sred->ksp,KSPPREONLY);CHKERRQ(ierr);
31114c9fce5SDave May       ierr = KSPSetInitialGuessNonzero(sred->ksp,pc->nonzero_guess);CHKERRQ(ierr);
3121e07b27eSBarry Smith       ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr);
3131e07b27eSBarry Smith       ierr = KSPSetOptionsPrefix(sred->ksp,prefix);CHKERRQ(ierr);
3141e07b27eSBarry Smith       ierr = KSPAppendOptionsPrefix(sred->ksp,"telescope_");CHKERRQ(ierr);
3151e07b27eSBarry Smith     }
3161e07b27eSBarry Smith   }
3171e07b27eSBarry Smith   /* Determine type of setup/update */
3181e07b27eSBarry Smith   if (!pc->setupcalled) {
3191e07b27eSBarry Smith     PetscBool has_dm,same;
3201e07b27eSBarry Smith     DM        dm;
3211e07b27eSBarry Smith 
3221e07b27eSBarry Smith     sr_type = TELESCOPE_DEFAULT;
3231e07b27eSBarry Smith     has_dm = PETSC_FALSE;
3241e07b27eSBarry Smith     ierr = PCGetDM(pc,&dm);CHKERRQ(ierr);
3251e07b27eSBarry Smith     if (dm) { has_dm = PETSC_TRUE; }
3261e07b27eSBarry Smith     if (has_dm) {
3271e07b27eSBarry Smith       /* check for dmda */
3281e07b27eSBarry Smith       ierr = PetscObjectTypeCompare((PetscObject)dm,DMDA,&same);CHKERRQ(ierr);
3291e07b27eSBarry Smith       if (same) {
3301e07b27eSBarry Smith         ierr = PetscInfo(pc,"PCTelescope: found DMDA\n");CHKERRQ(ierr);
3311e07b27eSBarry Smith         sr_type = TELESCOPE_DMDA;
3321e07b27eSBarry Smith       }
3331e07b27eSBarry Smith       /* check for dmplex */
3341e07b27eSBarry Smith       ierr = PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&same);CHKERRQ(ierr);
3351e07b27eSBarry Smith       if (same) {
3361e07b27eSBarry Smith         PetscInfo(pc,"PCTelescope: found DMPLEX\n");
3371e07b27eSBarry Smith         sr_type = TELESCOPE_DMPLEX;
3381e07b27eSBarry Smith       }
3391e07b27eSBarry Smith     }
3401e07b27eSBarry Smith 
3411e07b27eSBarry Smith     if (sred->ignore_dm) {
3421e07b27eSBarry Smith       PetscInfo(pc,"PCTelescope: ignore DM\n");
3431e07b27eSBarry Smith       sr_type = TELESCOPE_DEFAULT;
3441e07b27eSBarry Smith     }
3451e07b27eSBarry Smith     sred->sr_type = sr_type;
3461e07b27eSBarry Smith   } else {
3471e07b27eSBarry Smith     sr_type = sred->sr_type;
3481e07b27eSBarry Smith   }
3491e07b27eSBarry Smith 
3501e07b27eSBarry Smith   /* set function pointers for repartition setup, matrix creation/update, matrix nullspace and reset functionality */
3511e07b27eSBarry Smith   switch (sr_type) {
3521e07b27eSBarry Smith   case TELESCOPE_DEFAULT:
3531e07b27eSBarry Smith     sred->pctelescope_setup_type              = PCTelescopeSetUp_default;
3541e07b27eSBarry Smith     sred->pctelescope_matcreate_type          = PCTelescopeMatCreate_default;
3551e07b27eSBarry Smith     sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_default;
3561e07b27eSBarry Smith     sred->pctelescope_reset_type              = NULL;
3571e07b27eSBarry Smith     break;
3581e07b27eSBarry Smith   case TELESCOPE_DMDA:
3591e07b27eSBarry Smith     pc->ops->apply                          = PCApply_Telescope_dmda;
3601e07b27eSBarry Smith     sred->pctelescope_setup_type              = PCTelescopeSetUp_dmda;
3611e07b27eSBarry Smith     sred->pctelescope_matcreate_type          = PCTelescopeMatCreate_dmda;
3621e07b27eSBarry Smith     sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_dmda;
3631e07b27eSBarry Smith     sred->pctelescope_reset_type              = PCReset_Telescope_dmda;
3641e07b27eSBarry Smith     break;
3651e07b27eSBarry Smith   case TELESCOPE_DMPLEX: SETERRQ(comm,PETSC_ERR_SUP,"Supprt for DMPLEX is currently not available");
3661e07b27eSBarry Smith     break;
3671e07b27eSBarry Smith   default: SETERRQ(comm,PETSC_ERR_SUP,"Only supprt for repartitioning DMDA is provided");
3681e07b27eSBarry Smith     break;
3691e07b27eSBarry Smith   }
3701e07b27eSBarry Smith 
3711e07b27eSBarry Smith   /* setup */
3721e07b27eSBarry Smith   if (sred->pctelescope_setup_type) {
3731e07b27eSBarry Smith     ierr = sred->pctelescope_setup_type(pc,sred);CHKERRQ(ierr);
3741e07b27eSBarry Smith   }
3751e07b27eSBarry Smith   /* update */
3761e07b27eSBarry Smith   if (!pc->setupcalled) {
3771e07b27eSBarry Smith     if (sred->pctelescope_matcreate_type) {
3781e07b27eSBarry Smith       ierr = sred->pctelescope_matcreate_type(pc,sred,MAT_INITIAL_MATRIX,&sred->Bred);CHKERRQ(ierr);
3791e07b27eSBarry Smith     }
3801e07b27eSBarry Smith     if (sred->pctelescope_matnullspacecreate_type) {
3811e07b27eSBarry Smith       ierr = sred->pctelescope_matnullspacecreate_type(pc,sred,sred->Bred);CHKERRQ(ierr);
3821e07b27eSBarry Smith     }
3831e07b27eSBarry Smith   } else {
3841e07b27eSBarry Smith     if (sred->pctelescope_matcreate_type) {
3851e07b27eSBarry Smith       ierr = sred->pctelescope_matcreate_type(pc,sred,MAT_REUSE_MATRIX,&sred->Bred);CHKERRQ(ierr);
3861e07b27eSBarry Smith     }
3871e07b27eSBarry Smith   }
3881e07b27eSBarry Smith 
3891e07b27eSBarry Smith   /* common - no construction */
3901e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
3911e07b27eSBarry Smith     ierr = KSPSetOperators(sred->ksp,sred->Bred,sred->Bred);CHKERRQ(ierr);
3921e07b27eSBarry Smith     if (pc->setfromoptionscalled && !pc->setupcalled){
3931e07b27eSBarry Smith       ierr = KSPSetFromOptions(sred->ksp);CHKERRQ(ierr);
3941e07b27eSBarry Smith     }
3951e07b27eSBarry Smith   }
3961e07b27eSBarry Smith   PetscFunctionReturn(0);
3971e07b27eSBarry Smith }
3981e07b27eSBarry Smith 
3991e07b27eSBarry Smith #undef __FUNCT__
4001e07b27eSBarry Smith #define __FUNCT__ "PCApply_Telescope"
4011e07b27eSBarry Smith static PetscErrorCode PCApply_Telescope(PC pc,Vec x,Vec y)
4021e07b27eSBarry Smith {
4031e07b27eSBarry Smith   PC_Telescope      sred = (PC_Telescope)pc->data;
4041e07b27eSBarry Smith   PetscErrorCode    ierr;
4051e07b27eSBarry Smith   Vec               xtmp,xred,yred;
4061e07b27eSBarry Smith   PetscInt          i,st,ed,bs;
4071e07b27eSBarry Smith   VecScatter        scatter;
4081e07b27eSBarry Smith   PetscScalar       *array;
4091e07b27eSBarry Smith   const PetscScalar *x_array;
4101e07b27eSBarry Smith 
4111e07b27eSBarry Smith   PetscFunctionBegin;
4121e07b27eSBarry Smith   xtmp    = sred->xtmp;
4131e07b27eSBarry Smith   scatter = sred->scatter;
4141e07b27eSBarry Smith   xred    = sred->xred;
4151e07b27eSBarry Smith   yred    = sred->yred;
4161e07b27eSBarry Smith 
41714c9fce5SDave May   if (pc->nonzero_guess) {
41814c9fce5SDave May     ierr = PetscInfo(pc,"PCTelescope: Scattering y for non-zero-initial guess\n");CHKERRQ(ierr);
41914c9fce5SDave May     /* pull in vector y->xtmp */
42014c9fce5SDave May     ierr = VecScatterBegin(scatter,y,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
42114c9fce5SDave May     ierr = VecScatterEnd(scatter,y,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
42214c9fce5SDave May 
42314c9fce5SDave May     /* copy vector entires into xred */
42414c9fce5SDave May     ierr = VecGetBlockSize(xtmp,&bs);CHKERRQ(ierr);
42514c9fce5SDave May     ierr = VecGetArrayRead(xtmp,&x_array);CHKERRQ(ierr);
42614c9fce5SDave May     if (yred) {
42714c9fce5SDave May       PetscScalar *LA_yred;
42814c9fce5SDave May       ierr = VecGetOwnershipRange(yred,&st,&ed);CHKERRQ(ierr);
42914c9fce5SDave May       ierr = VecGetArray(yred,&LA_yred);CHKERRQ(ierr);
43014c9fce5SDave May       for (i=0; i<ed-st; i++) {
43114c9fce5SDave May         LA_yred[i] = x_array[i];
43214c9fce5SDave May       }
43314c9fce5SDave May       ierr = VecRestoreArray(yred,&LA_yred);CHKERRQ(ierr);
43414c9fce5SDave May     }
43514c9fce5SDave May     ierr = VecRestoreArrayRead(xtmp,&x_array);CHKERRQ(ierr);
43614c9fce5SDave May   }
43714c9fce5SDave May 
4381e07b27eSBarry Smith   /* pull in vector x->xtmp */
4391e07b27eSBarry Smith   ierr = VecScatterBegin(scatter,x,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4401e07b27eSBarry Smith   ierr = VecScatterEnd(scatter,x,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4411e07b27eSBarry Smith 
4421e07b27eSBarry Smith   /* copy vector entires into xred */
4431e07b27eSBarry Smith   ierr = VecGetBlockSize(xtmp,&bs);CHKERRQ(ierr);
4441e07b27eSBarry Smith   ierr = VecGetArrayRead(xtmp,&x_array);CHKERRQ(ierr);
4451e07b27eSBarry Smith   if (xred) {
4461e07b27eSBarry Smith     PetscScalar *LA_xred;
4471e07b27eSBarry Smith     ierr = VecGetOwnershipRange(xred,&st,&ed);CHKERRQ(ierr);
4481e07b27eSBarry Smith     ierr = VecGetArray(xred,&LA_xred);CHKERRQ(ierr);
4491e07b27eSBarry Smith     for (i=0; i<ed-st; i++) {
4501e07b27eSBarry Smith       LA_xred[i] = x_array[i];
4511e07b27eSBarry Smith     }
4521e07b27eSBarry Smith     ierr = VecRestoreArray(xred,&LA_xred);CHKERRQ(ierr);
4531e07b27eSBarry Smith   }
4541e07b27eSBarry Smith   ierr = VecRestoreArrayRead(xtmp,&x_array);CHKERRQ(ierr);
4551e07b27eSBarry Smith   /* solve */
4561e07b27eSBarry Smith   if (isActiveRank(sred->psubcomm)) {
4571e07b27eSBarry Smith     ierr = KSPSolve(sred->ksp,xred,yred);CHKERRQ(ierr);
4581e07b27eSBarry Smith   }
4591e07b27eSBarry Smith   /* return vector */
4601e07b27eSBarry Smith   ierr = VecGetBlockSize(xtmp,&bs);CHKERRQ(ierr);
4611e07b27eSBarry Smith   ierr = VecGetArray(xtmp,&array);CHKERRQ(ierr);
4621e07b27eSBarry Smith   if (yred) {
4631e07b27eSBarry Smith     const PetscScalar *LA_yred;
4641e07b27eSBarry Smith     ierr = VecGetOwnershipRange(yred,&st,&ed);CHKERRQ(ierr);
4651e07b27eSBarry Smith     ierr = VecGetArrayRead(yred,&LA_yred);CHKERRQ(ierr);
4661e07b27eSBarry Smith     for (i=0; i<ed-st; i++) {
4671e07b27eSBarry Smith       array[i] = LA_yred[i];
4681e07b27eSBarry Smith     }
4691e07b27eSBarry Smith     ierr = VecRestoreArrayRead(yred,&LA_yred);CHKERRQ(ierr);
4701e07b27eSBarry Smith   }
4711e07b27eSBarry Smith   ierr = VecRestoreArray(xtmp,&array);CHKERRQ(ierr);
4721e07b27eSBarry Smith   ierr = VecScatterBegin(scatter,xtmp,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4731e07b27eSBarry Smith   ierr = VecScatterEnd(scatter,xtmp,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4741e07b27eSBarry Smith   PetscFunctionReturn(0);
4751e07b27eSBarry Smith }
4761e07b27eSBarry Smith 
4771e07b27eSBarry Smith #undef __FUNCT__
4781e07b27eSBarry Smith #define __FUNCT__ "PCReset_Telescope"
4791e07b27eSBarry Smith static PetscErrorCode PCReset_Telescope(PC pc)
4801e07b27eSBarry Smith {
4811e07b27eSBarry Smith   PC_Telescope   sred = (PC_Telescope)pc->data;
4821e07b27eSBarry Smith   PetscErrorCode ierr;
4831e07b27eSBarry Smith 
4841e07b27eSBarry Smith   ierr = ISDestroy(&sred->isin);CHKERRQ(ierr);
4851e07b27eSBarry Smith   ierr = VecScatterDestroy(&sred->scatter);CHKERRQ(ierr);
486e3acf2f7SBarry Smith   ierr = VecDestroy(&sred->xred);CHKERRQ(ierr);
487e3acf2f7SBarry Smith   ierr = VecDestroy(&sred->yred);CHKERRQ(ierr);
488e3acf2f7SBarry Smith   ierr = VecDestroy(&sred->xtmp);CHKERRQ(ierr);
489e3acf2f7SBarry Smith   ierr = MatDestroy(&sred->Bred);CHKERRQ(ierr);
490e3acf2f7SBarry Smith   ierr = KSPReset(sred->ksp);CHKERRQ(ierr);
4911e07b27eSBarry Smith   if (sred->pctelescope_reset_type) {
4921e07b27eSBarry Smith     ierr = sred->pctelescope_reset_type(pc);CHKERRQ(ierr);
4931e07b27eSBarry Smith   }
4941e07b27eSBarry Smith   PetscFunctionReturn(0);
4951e07b27eSBarry Smith }
4961e07b27eSBarry Smith 
4971e07b27eSBarry Smith #undef __FUNCT__
4981e07b27eSBarry Smith #define __FUNCT__ "PCDestroy_Telescope"
4991e07b27eSBarry Smith static PetscErrorCode PCDestroy_Telescope(PC pc)
5001e07b27eSBarry Smith {
5011e07b27eSBarry Smith   PC_Telescope     sred = (PC_Telescope)pc->data;
5021e07b27eSBarry Smith   PetscErrorCode   ierr;
5031e07b27eSBarry Smith 
5041e07b27eSBarry Smith   PetscFunctionBegin;
5051e07b27eSBarry Smith   ierr = PCReset_Telescope(pc);CHKERRQ(ierr);
506e3acf2f7SBarry Smith   ierr = KSPDestroy(&sred->ksp);CHKERRQ(ierr);
5071e07b27eSBarry Smith   ierr = PetscSubcommDestroy(&sred->psubcomm);CHKERRQ(ierr);
508e3acf2f7SBarry Smith   ierr = PetscFree(sred->dm_ctx);CHKERRQ(ierr);
509e3acf2f7SBarry Smith   ierr = PetscFree(pc->data);CHKERRQ(ierr);
5101e07b27eSBarry Smith   PetscFunctionReturn(0);
5111e07b27eSBarry Smith }
5121e07b27eSBarry Smith 
5131e07b27eSBarry Smith #undef __FUNCT__
5141e07b27eSBarry Smith #define __FUNCT__ "PCSetFromOptions_Telescope"
5154416b707SBarry Smith static PetscErrorCode PCSetFromOptions_Telescope(PetscOptionItems *PetscOptionsObject,PC pc)
5161e07b27eSBarry Smith {
5171e07b27eSBarry Smith   PC_Telescope     sred = (PC_Telescope)pc->data;
5181e07b27eSBarry Smith   PetscErrorCode   ierr;
5191e07b27eSBarry Smith   MPI_Comm         comm;
5201e07b27eSBarry Smith   PetscMPIInt      size;
5211e07b27eSBarry Smith 
5221e07b27eSBarry Smith   PetscFunctionBegin;
5231e07b27eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
5241e07b27eSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
5251e07b27eSBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"Telescope options");CHKERRQ(ierr);
5261e07b27eSBarry Smith   ierr = PetscOptionsInt("-pc_telescope_reduction_factor","Factor to reduce comm size by","PCTelescopeSetReductionFactor",sred->redfactor,&sred->redfactor,0);CHKERRQ(ierr);
5271e07b27eSBarry Smith   if (sred->redfactor > size) SETERRQ(comm,PETSC_ERR_ARG_WRONG,"-pc_telescope_reduction_factor <= comm size");
5281e07b27eSBarry Smith   ierr = PetscOptionsBool("-pc_telescope_ignore_dm","Ignore any DM attached to the PC","PCTelescopeSetIgnoreDM",sred->ignore_dm,&sred->ignore_dm,0);CHKERRQ(ierr);
529*7c5279cbSDave May   ierr = PetscOptionsBool("-pc_telescope_ignore_kspcomputeoperators","Ignore method used to compute A","PCTelescopeSetIgnoreKSPComputeOperators",sred->ignore_kspcomputeoperators,&sred->ignore_kspcomputeoperators,0);CHKERRQ(ierr);
5301e07b27eSBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
5311e07b27eSBarry Smith   PetscFunctionReturn(0);
5321e07b27eSBarry Smith }
5331e07b27eSBarry Smith 
5341e07b27eSBarry Smith /* PC simplementation specific API's */
5351e07b27eSBarry Smith 
5361e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetKSP_Telescope(PC pc,KSP *ksp)
5371e07b27eSBarry Smith {
5381e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
539bd49479cSSatish Balay   PetscFunctionBegin;
5401e07b27eSBarry Smith   if (ksp) *ksp = red->ksp;
541bd49479cSSatish Balay   PetscFunctionReturn(0);
5421e07b27eSBarry Smith }
5431e07b27eSBarry Smith 
5441e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetReductionFactor_Telescope(PC pc,PetscInt *fact)
5451e07b27eSBarry Smith {
5461e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
547bd49479cSSatish Balay   PetscFunctionBegin;
5481e07b27eSBarry Smith   if (fact) *fact = red->redfactor;
549bd49479cSSatish Balay   PetscFunctionReturn(0);
5501e07b27eSBarry Smith }
5511e07b27eSBarry Smith 
5521e07b27eSBarry Smith static PetscErrorCode PCTelescopeSetReductionFactor_Telescope(PC pc,PetscInt fact)
5531e07b27eSBarry Smith {
5541e07b27eSBarry Smith   PC_Telescope     red = (PC_Telescope)pc->data;
5551e07b27eSBarry Smith   PetscMPIInt      size;
5561e07b27eSBarry Smith   PetscErrorCode   ierr;
5571e07b27eSBarry Smith 
558bd49479cSSatish Balay   PetscFunctionBegin;
5591e07b27eSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
5601e07b27eSBarry Smith   if (fact <= 0) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Reduction factor of telescoping PC %D must be positive",fact);
5611e07b27eSBarry Smith   if (fact > size) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Reduction factor of telescoping PC %D must be <= comm.size",fact);
5621e07b27eSBarry Smith   red->redfactor = fact;
563bd49479cSSatish Balay   PetscFunctionReturn(0);
5641e07b27eSBarry Smith }
5651e07b27eSBarry Smith 
5661e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetIgnoreDM_Telescope(PC pc,PetscBool *v)
5671e07b27eSBarry Smith {
5681e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
569bd49479cSSatish Balay   PetscFunctionBegin;
5701e07b27eSBarry Smith   if (v) *v = red->ignore_dm;
571bd49479cSSatish Balay   PetscFunctionReturn(0);
5721e07b27eSBarry Smith }
5731e07b27eSBarry Smith static PetscErrorCode PCTelescopeSetIgnoreDM_Telescope(PC pc,PetscBool v)
5741e07b27eSBarry Smith {
5751e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
576bd49479cSSatish Balay   PetscFunctionBegin;
5771e07b27eSBarry Smith   red->ignore_dm = v;
578bd49479cSSatish Balay   PetscFunctionReturn(0);
5791e07b27eSBarry Smith }
5801e07b27eSBarry Smith 
5811e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetDM_Telescope(PC pc,DM *dm)
5821e07b27eSBarry Smith {
5831e07b27eSBarry Smith   PC_Telescope red = (PC_Telescope)pc->data;
584bd49479cSSatish Balay   PetscFunctionBegin;
5851e07b27eSBarry Smith   *dm = private_PCTelescopeGetSubDM(red);
586bd49479cSSatish Balay   PetscFunctionReturn(0);
5871e07b27eSBarry Smith }
5881e07b27eSBarry Smith 
5891e07b27eSBarry Smith /*@
5901e07b27eSBarry Smith  PCTelescopeGetKSP - Gets the KSP created by the telescoping PC.
5911e07b27eSBarry Smith 
5921e07b27eSBarry Smith  Not Collective
5931e07b27eSBarry Smith 
5941e07b27eSBarry Smith  Input Parameter:
5951e07b27eSBarry Smith  .  pc - the preconditioner context
5961e07b27eSBarry Smith 
5971e07b27eSBarry Smith  Output Parameter:
5981e07b27eSBarry Smith  .  subksp - the KSP defined the smaller set of processes
5991e07b27eSBarry Smith 
6001e07b27eSBarry Smith  Level: advanced
6011e07b27eSBarry Smith 
6021e07b27eSBarry Smith  .keywords: PC, telescopting solve
6031e07b27eSBarry Smith  @*/
6041e07b27eSBarry Smith PetscErrorCode PCTelescopeGetKSP(PC pc,KSP *subksp)
6051e07b27eSBarry Smith {
606bd49479cSSatish Balay   PetscErrorCode ierr;
607bd49479cSSatish Balay   PetscFunctionBegin;
608bd49479cSSatish Balay   ierr = PetscTryMethod(pc,"PCTelescopeGetKSP_C",(PC,KSP*),(pc,subksp));CHKERRQ(ierr);
609bd49479cSSatish Balay   PetscFunctionReturn(0);
6101e07b27eSBarry Smith }
6111e07b27eSBarry Smith 
6121e07b27eSBarry Smith /*@
6131e07b27eSBarry Smith  PCTelescopeGetReductionFactor - Gets the factor by which the original number of processes has been reduced by.
6141e07b27eSBarry Smith 
6151e07b27eSBarry Smith  Not Collective
6161e07b27eSBarry Smith 
6171e07b27eSBarry Smith  Input Parameter:
6181e07b27eSBarry Smith  .  pc - the preconditioner context
6191e07b27eSBarry Smith 
6201e07b27eSBarry Smith  Output Parameter:
6211e07b27eSBarry Smith  .  fact - the reduction factor
6221e07b27eSBarry Smith 
6231e07b27eSBarry Smith  Level: advanced
6241e07b27eSBarry Smith 
6251e07b27eSBarry Smith  .keywords: PC, telescoping solve
6261e07b27eSBarry Smith  @*/
6271e07b27eSBarry Smith PetscErrorCode PCTelescopeGetReductionFactor(PC pc,PetscInt *fact)
6281e07b27eSBarry Smith {
629bd49479cSSatish Balay   PetscErrorCode ierr;
630bd49479cSSatish Balay   PetscFunctionBegin;
631bd49479cSSatish Balay   ierr = PetscTryMethod(pc,"PCTelescopeGetReductionFactor_C",(PC,PetscInt*),(pc,fact));CHKERRQ(ierr);
632bd49479cSSatish Balay   PetscFunctionReturn(0);
6331e07b27eSBarry Smith }
6341e07b27eSBarry Smith 
6351e07b27eSBarry Smith /*@
6361e07b27eSBarry Smith  PCTelescopeSetReductionFactor - Sets the factor by which the original number of processes has been reduced by.
6371e07b27eSBarry Smith 
6381e07b27eSBarry Smith  Not Collective
6391e07b27eSBarry Smith 
6401e07b27eSBarry Smith  Input Parameter:
6411e07b27eSBarry Smith  .  pc - the preconditioner context
6421e07b27eSBarry Smith 
6431e07b27eSBarry Smith  Output Parameter:
6441e07b27eSBarry Smith  .  fact - the reduction factor
6451e07b27eSBarry Smith 
6461e07b27eSBarry Smith  Level: advanced
6471e07b27eSBarry Smith 
6481e07b27eSBarry Smith  .keywords: PC, telescoping solve
6491e07b27eSBarry Smith  @*/
6501e07b27eSBarry Smith PetscErrorCode PCTelescopeSetReductionFactor(PC pc,PetscInt fact)
6511e07b27eSBarry Smith {
652bd49479cSSatish Balay   PetscErrorCode ierr;
653bd49479cSSatish Balay   PetscFunctionBegin;
654bd49479cSSatish Balay   ierr = PetscTryMethod(pc,"PCTelescopeSetReductionFactor_C",(PC,PetscInt),(pc,fact));CHKERRQ(ierr);
655bd49479cSSatish Balay   PetscFunctionReturn(0);
6561e07b27eSBarry Smith }
6571e07b27eSBarry Smith 
6581e07b27eSBarry Smith /*@
6591e07b27eSBarry Smith  PCTelescopeGetIgnoreDM - Get the flag indicating if any DM attached to the PC will be used.
6601e07b27eSBarry Smith 
6611e07b27eSBarry Smith  Not Collective
6621e07b27eSBarry Smith 
6631e07b27eSBarry Smith  Input Parameter:
6641e07b27eSBarry Smith  .  pc - the preconditioner context
6651e07b27eSBarry Smith 
6661e07b27eSBarry Smith  Output Parameter:
6671e07b27eSBarry Smith  .  v - the flag
6681e07b27eSBarry Smith 
6691e07b27eSBarry Smith  Level: advanced
6701e07b27eSBarry Smith 
6711e07b27eSBarry Smith  .keywords: PC, telescoping solve
6721e07b27eSBarry Smith  @*/
6731e07b27eSBarry Smith PetscErrorCode PCTelescopeGetIgnoreDM(PC pc,PetscBool *v)
6741e07b27eSBarry Smith {
675bd49479cSSatish Balay   PetscErrorCode ierr;
676bd49479cSSatish Balay   PetscFunctionBegin;
677bd49479cSSatish Balay   ierr = PetscTryMethod(pc,"PCTelescopeGetIgnoreDM_C",(PC,PetscBool*),(pc,v));CHKERRQ(ierr);
678bd49479cSSatish Balay   PetscFunctionReturn(0);
6791e07b27eSBarry Smith }
6801e07b27eSBarry Smith 
6811e07b27eSBarry Smith /*@
6821e07b27eSBarry Smith  PCTelescopeSetIgnoreDM - Set a flag to ignore any DM attached to the PC.
6831e07b27eSBarry Smith 
6841e07b27eSBarry Smith  Not Collective
6851e07b27eSBarry Smith 
6861e07b27eSBarry Smith  Input Parameter:
6871e07b27eSBarry Smith  .  pc - the preconditioner context
6881e07b27eSBarry Smith 
6891e07b27eSBarry Smith  Output Parameter:
6901e07b27eSBarry Smith  .  v - Use PETSC_TRUE to ignore any DM
6911e07b27eSBarry Smith 
6921e07b27eSBarry Smith  Level: advanced
6931e07b27eSBarry Smith 
6941e07b27eSBarry Smith  .keywords: PC, telescoping solve
6951e07b27eSBarry Smith  @*/
696bfd6bcc6SSatish Balay PetscErrorCode PCTelescopeSetIgnoreDM(PC pc,PetscBool v)
6971e07b27eSBarry Smith {
698bd49479cSSatish Balay   PetscErrorCode ierr;
699bd49479cSSatish Balay   PetscFunctionBegin;
700bd49479cSSatish Balay   ierr = PetscTryMethod(pc,"PCTelescopeSetIgnoreDM_C",(PC,PetscBool),(pc,v));CHKERRQ(ierr);
701bd49479cSSatish Balay   PetscFunctionReturn(0);
7021e07b27eSBarry Smith }
7031e07b27eSBarry Smith 
7041e07b27eSBarry Smith /*@
7051e07b27eSBarry Smith  PCTelescopeGetDM - Get the re-partitioned DM attached to the sub KSP.
7061e07b27eSBarry Smith 
7071e07b27eSBarry Smith  Not Collective
7081e07b27eSBarry Smith 
7091e07b27eSBarry Smith  Input Parameter:
7101e07b27eSBarry Smith  .  pc - the preconditioner context
7111e07b27eSBarry Smith 
7121e07b27eSBarry Smith  Output Parameter:
7131e07b27eSBarry Smith  .  subdm - The re-partitioned DM
7141e07b27eSBarry Smith 
7151e07b27eSBarry Smith  Level: advanced
7161e07b27eSBarry Smith 
7171e07b27eSBarry Smith  .keywords: PC, telescoping solve
7181e07b27eSBarry Smith  @*/
7191e07b27eSBarry Smith PetscErrorCode PCTelescopeGetDM(PC pc,DM *subdm)
7201e07b27eSBarry Smith {
721bd49479cSSatish Balay   PetscErrorCode ierr;
722bd49479cSSatish Balay   PetscFunctionBegin;
723bd49479cSSatish Balay   ierr = PetscTryMethod(pc,"PCTelescopeGetDM_C",(PC,DM*),(pc,subdm));CHKERRQ(ierr);
724bd49479cSSatish Balay   PetscFunctionReturn(0);
7251e07b27eSBarry Smith }
7261e07b27eSBarry Smith 
7271e07b27eSBarry Smith /* -------------------------------------------------------------------------------------*/
7281e07b27eSBarry Smith /*MC
7291e07b27eSBarry Smith    PCTELESCOPE - Runs a KSP solver on a sub-group of processors. MPI processes not in the sub-communicator are idle during the solve.
7301e07b27eSBarry Smith 
7311e07b27eSBarry Smith    Options Database:
7321e07b27eSBarry Smith +  -pc_telescope_reduction_factor <n> - factor to use communicator size by, for example if you are using 64 MPI processes and
7331e07b27eSBarry Smith    use an n of 4, the new sub-communicator will be 4 defined with 64/4 processes
7341e07b27eSBarry Smith -  -pc_telescope_ignore_dm <false> - flag to indicate whether an attached DM should be ignored
7351e07b27eSBarry Smith 
7361e07b27eSBarry Smith    Level: advanced
7371e07b27eSBarry Smith 
7381e07b27eSBarry Smith    Notes:
7396fc41876SBarry Smith    The preconditioner is deemed telescopic as it only calls KSPSolve() on a single
7406fc41876SBarry Smith    sub-communicator in contrast with PCREDUNDANT which calls KSPSolve() on N sub-communicators.
7416fc41876SBarry Smith    This means there will be MPI processes within c, which will be idle during the application of this preconditioner.
7426fc41876SBarry Smith 
7431e07b27eSBarry Smith    The default KSP is PREONLY. If a DM is attached to the PC, it is re-partitioned on the sub-communicator.
7441e07b27eSBarry 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.
7451e07b27eSBarry Smith    Currently only support for re-partitioning a DMDA is provided.
7461e07b27eSBarry Smith    Any nullspace attached to the original Bmat operator are extracted, re-partitioned and set on the repartitioned Bmat operator.
7471e07b27eSBarry Smith    KSPSetComputeOperators() is not propagated to the sub KSP.
7481e07b27eSBarry Smith    Currently there is no support for the flag -pc_use_amat
7491e07b27eSBarry Smith 
7506fc41876SBarry Smith    Assuming that the parent preconditioner (PC) is defined on a communicator c, this implementation
7516fc41876SBarry Smith    creates a child sub-communicator (c') containing less MPI processes than the original parent preconditioner (PC).
7526fc41876SBarry Smith 
7536fc41876SBarry Smith   Developer Notes:
7546fc41876SBarry Smith    During PCSetup, the B operator is scattered onto c'.
7556fc41876SBarry Smith    Within PCApply, the RHS vector (x) is scattered into a redundant vector, xred (defined on c').
7566fc41876SBarry Smith    Then KSPSolve() is executed on the c' communicator.
7576fc41876SBarry Smith 
7586fc41876SBarry Smith    The communicator used within the telescoping preconditioner is defined by a PetscSubcomm using the INTERLACED
7596fc41876SBarry Smith    creation routine. We run the sub KSP on only the ranks within the communicator which have a color equal to zero.
7606fc41876SBarry Smith 
7616fc41876SBarry Smith    The telescoping preconditioner is aware of nullspaces which are attached to the only B operator.
7626fc41876SBarry Smith    In case where B has a n nullspace attached, these nullspaces vectors are extract from B and mapped into
7636fc41876SBarry Smith    a new nullspace (defined on the sub-communicator) which is attached to B' (the B operator which was scattered to c')
7646fc41876SBarry Smith 
7656fc41876SBarry Smith    The telescoping preconditioner is aware of an attached DM. In the event that the DM is of type DMDA (2D or 3D -
7666fc41876SBarry 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
7676fc41876SBarry Smith    is attached the sub KSPSolve(). The design of telescope is such that it should be possible to extend support
7686fc41876SBarry Smith    for re-partitioning other DM's (e.g. DMPLEX). The user can supply a flag to ignore attached DMs.
7696fc41876SBarry Smith 
7706fc41876SBarry Smith    By default, B' is defined by simply fusing rows from different MPI processes
7716fc41876SBarry Smith 
7726fc41876SBarry Smith    When a DMDA is attached to the parent preconditioner, B' is defined by: (i) performing a symmetric permuting of B
7736fc41876SBarry Smith    into the ordering defined by the DMDA on c', (ii) extracting the local chunks via MatGetSubMatrices(), (iii) fusing the
7746fc41876SBarry Smith    locally (sequential) matrices defined on the ranks common to c and c' into B' using MatCreateMPIMatConcatenateSeqMat()
7756fc41876SBarry Smith 
7766fc41876SBarry Smith    Limitations/improvements
7776fc41876SBarry Smith    VecPlaceArray could be used within PCApply() to improve efficiency and reduce memory usage.
7786fc41876SBarry Smith 
7796fc41876SBarry Smith    The symmetric permutation used when a DMDA is encountered is performed via explicitly assmbleming a permutation matrix P,
7806fc41876SBarry 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
7816fc41876SBarry Smith    VecPermute() does not supported for the use case required here. By computing P, I can permute both the operator and RHS in a
7826fc41876SBarry Smith    consistent manner.
7836fc41876SBarry Smith 
7846fc41876SBarry Smith    Mapping of vectors is performed this way
7856fc41876SBarry 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.
7866fc41876SBarry Smith    Using the interlaced creation routine, the ranks in c with color = 0, will be rank 0 and 2.
7876fc41876SBarry Smith    We perform the scatter to the sub-comm in the following way,
7886fc41876SBarry Smith    [1] Given a vector x defined on comm c
7896fc41876SBarry Smith 
7906fc41876SBarry Smith    rank(c) : _________ 0 ______  ________ 1 _______  ________ 2 _____________ ___________ 3 __________
7916fc41876SBarry 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]
7926fc41876SBarry Smith 
7936fc41876SBarry Smith    scatter to xtmp defined also on comm c so that we have the following values
7946fc41876SBarry Smith 
7956fc41876SBarry Smith    rank(c) : ___________________ 0 ________________  _1_  ______________________ 2 _______________________  __3_
7966fc41876SBarry 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] [  ]
7976fc41876SBarry Smith 
7986fc41876SBarry Smith    The entries on rank 1 and 3 (ranks which do not have a color = 0 in c') have no values
7996fc41876SBarry Smith 
8006fc41876SBarry Smith 
8016fc41876SBarry 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'.
8026fc41876SBarry Smith    Ranks 0 and 2 are the only ranks in the subcomm which have a color = 0.
8036fc41876SBarry Smith 
8046fc41876SBarry Smith     rank(c') : ___________________ 0 _______________  ______________________ 1 _____________________
8056fc41876SBarry 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]
8066fc41876SBarry Smith 
8071e07b27eSBarry Smith 
8081e07b27eSBarry Smith   Contributed by Dave May
8091e07b27eSBarry Smith 
8106fc41876SBarry Smith .seealso:  PCTelescopeGetKSP(), PCTelescopeGetDM(), PCTelescopeGetReductionFactor(), PCTelescopeSetReductionFactor(), PCTelescopeGetIgnoreDM(), PCTelescopeSetIgnoreDM(), PCREDUNDANT
8111e07b27eSBarry Smith M*/
8121e07b27eSBarry Smith #undef __FUNCT__
8131e07b27eSBarry Smith #define __FUNCT__ "PCCreate_Telescope"
8141e07b27eSBarry Smith PETSC_EXTERN PetscErrorCode PCCreate_Telescope(PC pc)
8151e07b27eSBarry Smith {
8161e07b27eSBarry Smith   PetscErrorCode       ierr;
8171e07b27eSBarry Smith   struct _PC_Telescope *sred;
8181e07b27eSBarry Smith 
8191e07b27eSBarry Smith   PetscFunctionBegin;
8201e07b27eSBarry Smith   ierr = PetscNewLog(pc,&sred);CHKERRQ(ierr);
8211e07b27eSBarry Smith   sred->redfactor      = 1;
8221e07b27eSBarry Smith   sred->ignore_dm      = PETSC_FALSE;
823*7c5279cbSDave May   sred->ignore_kspcomputeoperators = PETSC_FALSE;
8241e07b27eSBarry Smith   pc->data             = (void*)sred;
8251e07b27eSBarry Smith 
8261e07b27eSBarry Smith   pc->ops->apply          = PCApply_Telescope;
8271e07b27eSBarry Smith   pc->ops->applytranspose = NULL;
8281e07b27eSBarry Smith   pc->ops->setup          = PCSetUp_Telescope;
8291e07b27eSBarry Smith   pc->ops->destroy        = PCDestroy_Telescope;
8301e07b27eSBarry Smith   pc->ops->reset          = PCReset_Telescope;
8311e07b27eSBarry Smith   pc->ops->setfromoptions = PCSetFromOptions_Telescope;
8321e07b27eSBarry Smith   pc->ops->view           = PCView_Telescope;
8331e07b27eSBarry Smith 
8341e07b27eSBarry Smith   sred->pctelescope_setup_type              = PCTelescopeSetUp_default;
8351e07b27eSBarry Smith   sred->pctelescope_matcreate_type          = PCTelescopeMatCreate_default;
8361e07b27eSBarry Smith   sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_default;
8371e07b27eSBarry Smith   sred->pctelescope_reset_type              = NULL;
8381e07b27eSBarry Smith 
8391e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetKSP_C",PCTelescopeGetKSP_Telescope);CHKERRQ(ierr);
8401e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetReductionFactor_C",PCTelescopeGetReductionFactor_Telescope);CHKERRQ(ierr);
8411e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetReductionFactor_C",PCTelescopeSetReductionFactor_Telescope);CHKERRQ(ierr);
8421e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetIgnoreDM_C",PCTelescopeGetIgnoreDM_Telescope);CHKERRQ(ierr);
8431e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetIgnoreDM_C",PCTelescopeSetIgnoreDM_Telescope);CHKERRQ(ierr);
8441e07b27eSBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetDM_C",PCTelescopeGetDM_Telescope);CHKERRQ(ierr);
8451e07b27eSBarry Smith   PetscFunctionReturn(0);
8461e07b27eSBarry Smith }
847