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