1*1e07b27eSBarry Smith 2*1e07b27eSBarry Smith /* 3*1e07b27eSBarry Smith 4*1e07b27eSBarry Smith Defines a telescoping preconditioner 5*1e07b27eSBarry Smith 6*1e07b27eSBarry Smith Assuming that the parent preconditioner (PC) is defined on a communicator c, this implementation 7*1e07b27eSBarry Smith creates a child sub-communicator (c') containing less MPI processes than the original parent preconditioner (PC). 8*1e07b27eSBarry Smith 9*1e07b27eSBarry Smith During PCSetup, the B operator is scattered onto c'. 10*1e07b27eSBarry Smith Within PCApply, the RHS vector (x) is scattered into a redundant vector, xred (defined on c'). 11*1e07b27eSBarry Smith Then KSPSolve() is executed on the c' communicator. 12*1e07b27eSBarry Smith 13*1e07b27eSBarry Smith The preconditioner is deemed telescopint as it only calls KSPSolve() on a single 14*1e07b27eSBarry Smith sub-communicator in contrast with PCREDUNDANT which calls KSPSolve() on N sub-communicators. 15*1e07b27eSBarry Smith This means there will be MPI processes within c, which will be idle during the application of this preconditioner. 16*1e07b27eSBarry Smith 17*1e07b27eSBarry Smith Comments: 18*1e07b27eSBarry Smith - The communicator used within the telescoping preconditioner is defined by a PetscSubcomm using the INTERLACED 19*1e07b27eSBarry Smith creation routine. We run the sub KSP on only the ranks within the communicator which have a color equal to zero. 20*1e07b27eSBarry Smith 21*1e07b27eSBarry Smith - The telescoping preconditioner is aware of nullspaces which are attached to the only B operator. 22*1e07b27eSBarry Smith In case where B has a n nullspace attached, these nullspaces vectors are extract from B and mapped into 23*1e07b27eSBarry Smith a new nullspace (defined on the sub-communicator) which is attached to B' (the B operator which was scattered to c') 24*1e07b27eSBarry Smith 25*1e07b27eSBarry Smith - The telescoping preconditioner is aware of an attached DM. In the event that the DM is of type DMDA (2D or 3D - 26*1e07b27eSBarry 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 27*1e07b27eSBarry Smith is attached the sub KSPSolve(). The design of telescope is such that it should be possible to extend support 28*1e07b27eSBarry Smith for re-partitioning other DM's (e.g. DMPLEX). The user can supply a flag to ignore attached DMs. 29*1e07b27eSBarry Smith 30*1e07b27eSBarry Smith - By default, B' is defined by simply fusing rows from different MPI processes 31*1e07b27eSBarry Smith 32*1e07b27eSBarry Smith - When a DMDA is attached to the parent preconditioner, B' is defined by: (i) performing a symmetric permuting of B 33*1e07b27eSBarry Smith into the ordering defined by the DMDA on c', (ii) extracting the local chunks via MatGetSubMatrices(), (iii) fusing the 34*1e07b27eSBarry Smith locally (sequential) matrices defined on the ranks common to c and c' into B' using MatCreateMPIMatConcatenateSeqMat() 35*1e07b27eSBarry Smith 36*1e07b27eSBarry Smith Limitations/improvements 37*1e07b27eSBarry Smith - VecPlaceArray could be used within PCApply() to improve efficiency and reduce memory usage. 38*1e07b27eSBarry Smith 39*1e07b27eSBarry Smith - The symmetric permutation used when a DMDA is encountered is performed via explicitly assmbleming a permutation matrix P, 40*1e07b27eSBarry 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 41*1e07b27eSBarry Smith VecPermute() does not supported for the use case required here. By computing P, I can permute both the operator and RHS in a 42*1e07b27eSBarry Smith consistent manner. 43*1e07b27eSBarry Smith 44*1e07b27eSBarry Smith - Mapping of vectors is performed this way 45*1e07b27eSBarry 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. 46*1e07b27eSBarry Smith Using the interlaced creation routine, the ranks in c with color = 0, will be rank 0 and 2. 47*1e07b27eSBarry Smith We perform the scatter to the sub-comm in the following way, 48*1e07b27eSBarry Smith [1] Given a vector x defined on comm c 49*1e07b27eSBarry Smith 50*1e07b27eSBarry Smith rank(c) : _________ 0 ______ ________ 1 _______ ________ 2 _____________ ___________ 3 __________ 51*1e07b27eSBarry 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] 52*1e07b27eSBarry Smith 53*1e07b27eSBarry Smith scatter to xtmp defined also on comm c so that we have the following values 54*1e07b27eSBarry Smith 55*1e07b27eSBarry Smith rank(c) : ___________________ 0 ________________ _1_ ______________________ 2 _______________________ __3_ 56*1e07b27eSBarry Smith xtmp : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] [ 6 ] [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23] [ 18 ] 57*1e07b27eSBarry Smith 58*1e07b27eSBarry Smith The entries on rank 1 and 3 (ranks which do not have a color = 0 in c') are filled with the first bs values living on that rank, 59*1e07b27eSBarry Smith where bs is the block size of the vector. 60*1e07b27eSBarry Smith 61*1e07b27eSBarry 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'. 62*1e07b27eSBarry Smith Ranks 0 and 2 are the only ranks in the subcomm which have a color = 0. 63*1e07b27eSBarry Smith 64*1e07b27eSBarry Smith rank(c') : ___________________ 0 _______________ ______________________ 1 _____________________ 65*1e07b27eSBarry 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] 66*1e07b27eSBarry Smith 67*1e07b27eSBarry Smith */ 68*1e07b27eSBarry Smith 69*1e07b27eSBarry Smith #include <petsc/private/pcimpl.h> /*I "petscpc.h" I*/ 70*1e07b27eSBarry Smith #include <petscksp.h> /*I "petscksp.h" I*/ 71*1e07b27eSBarry Smith #include <petscdm.h> /*I "petscdm.h" I*/ 72*1e07b27eSBarry Smith 73*1e07b27eSBarry Smith #include "telescope.h" 74*1e07b27eSBarry Smith 75*1e07b27eSBarry Smith /* 76*1e07b27eSBarry Smith PCTelescopeSetUp_default() 77*1e07b27eSBarry Smith PCTelescopeMatCreate_default() 78*1e07b27eSBarry Smith 79*1e07b27eSBarry Smith default 80*1e07b27eSBarry Smith 81*1e07b27eSBarry Smith // scatter in 82*1e07b27eSBarry Smith x(comm) -> xtmp(comm) 83*1e07b27eSBarry Smith 84*1e07b27eSBarry Smith xred(subcomm) <- xtmp 85*1e07b27eSBarry Smith yred(subcomm) 86*1e07b27eSBarry Smith 87*1e07b27eSBarry Smith yred(subcomm) --> xtmp 88*1e07b27eSBarry Smith 89*1e07b27eSBarry Smith // scatter out 90*1e07b27eSBarry Smith xtmp(comm) -> y(comm) 91*1e07b27eSBarry Smith */ 92*1e07b27eSBarry Smith 93*1e07b27eSBarry Smith PetscBool isActiveRank(PetscSubcomm scomm) 94*1e07b27eSBarry Smith { 95*1e07b27eSBarry Smith if (scomm->color == 0) { return PETSC_TRUE; } 96*1e07b27eSBarry Smith else { return PETSC_FALSE; } 97*1e07b27eSBarry Smith } 98*1e07b27eSBarry Smith 99*1e07b27eSBarry Smith #undef __FUNCT__ 100*1e07b27eSBarry Smith #define __FUNCT__ "private_PCTelescopeGetSubDM" 101*1e07b27eSBarry Smith DM private_PCTelescopeGetSubDM(PC_Telescope sred) 102*1e07b27eSBarry Smith { 103*1e07b27eSBarry Smith DM subdm; 104*1e07b27eSBarry Smith 105*1e07b27eSBarry Smith if (!isActiveRank(sred->psubcomm)) { subdm = NULL; } 106*1e07b27eSBarry Smith else { 107*1e07b27eSBarry Smith switch (sred->sr_type) { 108*1e07b27eSBarry Smith case TELESCOPE_DEFAULT: subdm = NULL; 109*1e07b27eSBarry Smith break; 110*1e07b27eSBarry Smith case TELESCOPE_DMDA: subdm = ((PC_Telescope_DMDACtx*)sred->dm_ctx)->dmrepart; 111*1e07b27eSBarry Smith break; 112*1e07b27eSBarry Smith case TELESCOPE_DMPLEX: subdm = NULL; 113*1e07b27eSBarry Smith break; 114*1e07b27eSBarry Smith } 115*1e07b27eSBarry Smith } 116*1e07b27eSBarry Smith return(subdm); 117*1e07b27eSBarry Smith } 118*1e07b27eSBarry Smith 119*1e07b27eSBarry Smith #undef __FUNCT__ 120*1e07b27eSBarry Smith #define __FUNCT__ "PCTelescopeSetUp_default" 121*1e07b27eSBarry Smith PetscErrorCode PCTelescopeSetUp_default(PC pc,PC_Telescope sred) 122*1e07b27eSBarry Smith { 123*1e07b27eSBarry Smith PetscErrorCode ierr; 124*1e07b27eSBarry Smith PetscInt m,M,bs,st,ed; 125*1e07b27eSBarry Smith Vec x,xred,yred,xtmp; 126*1e07b27eSBarry Smith Mat B; 127*1e07b27eSBarry Smith MPI_Comm comm,subcomm; 128*1e07b27eSBarry Smith VecScatter scatter; 129*1e07b27eSBarry Smith IS isin; 130*1e07b27eSBarry Smith 131*1e07b27eSBarry Smith PetscFunctionBegin; 132*1e07b27eSBarry Smith ierr = PetscInfo(pc,"PCTelescope: setup (default)\n");CHKERRQ(ierr); 133*1e07b27eSBarry Smith comm = PetscSubcommParent(sred->psubcomm); 134*1e07b27eSBarry Smith subcomm = PetscSubcommChild(sred->psubcomm); 135*1e07b27eSBarry Smith 136*1e07b27eSBarry Smith ierr = PCGetOperators(pc,NULL,&B);CHKERRQ(ierr); 137*1e07b27eSBarry Smith ierr = MatGetSize(B,&M,NULL);CHKERRQ(ierr); 138*1e07b27eSBarry Smith ierr = MatGetBlockSize(B,&bs);CHKERRQ(ierr); 139*1e07b27eSBarry Smith ierr = MatCreateVecs(B,&x,NULL);CHKERRQ(ierr); 140*1e07b27eSBarry Smith 141*1e07b27eSBarry Smith xred = NULL; 142*1e07b27eSBarry Smith m = bs; 143*1e07b27eSBarry Smith if (isActiveRank(sred->psubcomm)) { 144*1e07b27eSBarry Smith ierr = VecCreate(subcomm,&xred);CHKERRQ(ierr); 145*1e07b27eSBarry Smith ierr = VecSetSizes(xred,PETSC_DECIDE,M);CHKERRQ(ierr); 146*1e07b27eSBarry Smith ierr = VecSetBlockSize(xred,bs);CHKERRQ(ierr); 147*1e07b27eSBarry Smith ierr = VecSetFromOptions(xred);CHKERRQ(ierr); 148*1e07b27eSBarry Smith ierr = VecGetLocalSize(xred,&m); 149*1e07b27eSBarry Smith } 150*1e07b27eSBarry Smith 151*1e07b27eSBarry Smith yred = NULL; 152*1e07b27eSBarry Smith if (isActiveRank(sred->psubcomm)) { 153*1e07b27eSBarry Smith ierr = VecDuplicate(xred,&yred);CHKERRQ(ierr); 154*1e07b27eSBarry Smith } 155*1e07b27eSBarry Smith 156*1e07b27eSBarry Smith ierr = VecCreate(comm,&xtmp);CHKERRQ(ierr); 157*1e07b27eSBarry Smith ierr = VecSetSizes(xtmp,m,PETSC_DECIDE);CHKERRQ(ierr); 158*1e07b27eSBarry Smith ierr = VecSetBlockSize(xtmp,bs);CHKERRQ(ierr); 159*1e07b27eSBarry Smith ierr = VecSetType(xtmp,((PetscObject)x)->type_name);CHKERRQ(ierr); 160*1e07b27eSBarry Smith 161*1e07b27eSBarry Smith if (isActiveRank(sred->psubcomm)) { 162*1e07b27eSBarry Smith ierr = VecGetOwnershipRange(xred,&st,&ed);CHKERRQ(ierr); 163*1e07b27eSBarry Smith ierr = ISCreateStride(comm,(ed-st),st,1,&isin);CHKERRQ(ierr); 164*1e07b27eSBarry Smith } else { 165*1e07b27eSBarry Smith ierr = VecGetOwnershipRange(x,&st,&ed);CHKERRQ(ierr); 166*1e07b27eSBarry Smith ierr = ISCreateStride(comm,bs,st,1,&isin);CHKERRQ(ierr); 167*1e07b27eSBarry Smith } 168*1e07b27eSBarry Smith ierr = ISSetBlockSize(isin,bs);CHKERRQ(ierr); 169*1e07b27eSBarry Smith 170*1e07b27eSBarry Smith ierr = VecScatterCreate(x,isin,xtmp,NULL,&scatter);CHKERRQ(ierr); 171*1e07b27eSBarry Smith 172*1e07b27eSBarry Smith sred->isin = isin; 173*1e07b27eSBarry Smith sred->scatter = scatter; 174*1e07b27eSBarry Smith sred->xred = xred; 175*1e07b27eSBarry Smith sred->yred = yred; 176*1e07b27eSBarry Smith sred->xtmp = xtmp; 177*1e07b27eSBarry Smith ierr = VecDestroy(&x);CHKERRQ(ierr); 178*1e07b27eSBarry Smith PetscFunctionReturn(0); 179*1e07b27eSBarry Smith } 180*1e07b27eSBarry Smith 181*1e07b27eSBarry Smith #undef __FUNCT__ 182*1e07b27eSBarry Smith #define __FUNCT__ "PCTelescopeMatCreate_default" 183*1e07b27eSBarry Smith PetscErrorCode PCTelescopeMatCreate_default(PC pc,PC_Telescope sred,MatReuse reuse,Mat *A) 184*1e07b27eSBarry Smith { 185*1e07b27eSBarry Smith PetscErrorCode ierr; 186*1e07b27eSBarry Smith MPI_Comm comm,subcomm; 187*1e07b27eSBarry Smith Mat Bred,B; 188*1e07b27eSBarry Smith PetscInt nr,nc; 189*1e07b27eSBarry Smith IS isrow,iscol; 190*1e07b27eSBarry Smith Mat Blocal,*_Blocal; 191*1e07b27eSBarry Smith 192*1e07b27eSBarry Smith PetscFunctionBegin; 193*1e07b27eSBarry Smith ierr = PetscInfo(pc,"PCTelescope: updating the redundant preconditioned operator (default)\n");CHKERRQ(ierr); 194*1e07b27eSBarry Smith ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr); 195*1e07b27eSBarry Smith subcomm = PetscSubcommChild(sred->psubcomm); 196*1e07b27eSBarry Smith ierr = PCGetOperators(pc,NULL,&B);CHKERRQ(ierr); 197*1e07b27eSBarry Smith ierr = MatGetSize(B,&nr,&nc);CHKERRQ(ierr); 198*1e07b27eSBarry Smith isrow = sred->isin; 199*1e07b27eSBarry Smith ierr = ISCreateStride(comm,nc,0,1,&iscol);CHKERRQ(ierr); 200*1e07b27eSBarry Smith ierr = MatGetSubMatrices(B,1,&isrow,&iscol,MAT_INITIAL_MATRIX,&_Blocal);CHKERRQ(ierr); 201*1e07b27eSBarry Smith Blocal = *_Blocal; 202*1e07b27eSBarry Smith ierr = PetscFree(_Blocal);CHKERRQ(ierr); 203*1e07b27eSBarry Smith Bred = NULL; 204*1e07b27eSBarry Smith if (isActiveRank(sred->psubcomm)) { 205*1e07b27eSBarry Smith PetscInt mm; 206*1e07b27eSBarry Smith 207*1e07b27eSBarry Smith if (reuse != MAT_INITIAL_MATRIX) { Bred = *A; } 208*1e07b27eSBarry Smith 209*1e07b27eSBarry Smith ierr = MatGetSize(Blocal,&mm,NULL);CHKERRQ(ierr); 210*1e07b27eSBarry Smith //ierr = MatCreateMPIMatConcatenateSeqMat(subcomm,Blocal,PETSC_DECIDE,reuse,&Bred);CHKERRQ(ierr); 211*1e07b27eSBarry Smith ierr = MatCreateMPIMatConcatenateSeqMat(subcomm,Blocal,mm,reuse,&Bred);CHKERRQ(ierr); 212*1e07b27eSBarry Smith } 213*1e07b27eSBarry Smith *A = Bred; 214*1e07b27eSBarry Smith ierr = ISDestroy(&iscol);CHKERRQ(ierr); 215*1e07b27eSBarry Smith ierr = MatDestroy(&Blocal);CHKERRQ(ierr); 216*1e07b27eSBarry Smith PetscFunctionReturn(0); 217*1e07b27eSBarry Smith } 218*1e07b27eSBarry Smith 219*1e07b27eSBarry Smith #undef __FUNCT__ 220*1e07b27eSBarry Smith #define __FUNCT__ "PCTelescopeMatNullSpaceCreate_default" 221*1e07b27eSBarry Smith PetscErrorCode PCTelescopeMatNullSpaceCreate_default(PC pc,PC_Telescope sred,Mat sub_mat) 222*1e07b27eSBarry Smith { 223*1e07b27eSBarry Smith PetscErrorCode ierr; 224*1e07b27eSBarry Smith MatNullSpace nullspace,sub_nullspace; 225*1e07b27eSBarry Smith Mat A,B; 226*1e07b27eSBarry Smith PetscBool has_const; 227*1e07b27eSBarry Smith PetscInt i,k,n; 228*1e07b27eSBarry Smith const Vec *vecs; 229*1e07b27eSBarry Smith Vec *sub_vecs; 230*1e07b27eSBarry Smith MPI_Comm subcomm; 231*1e07b27eSBarry Smith 232*1e07b27eSBarry Smith PetscFunctionBegin; 233*1e07b27eSBarry Smith ierr = PCGetOperators(pc,&A,&B);CHKERRQ(ierr); 234*1e07b27eSBarry Smith ierr = MatGetNullSpace(B,&nullspace);CHKERRQ(ierr); 235*1e07b27eSBarry Smith if (!nullspace) return(0); 236*1e07b27eSBarry Smith 237*1e07b27eSBarry Smith ierr = PetscInfo(pc,"PCTelescope: generating nullspace (default)\n");CHKERRQ(ierr); 238*1e07b27eSBarry Smith subcomm = PetscSubcommChild(sred->psubcomm); 239*1e07b27eSBarry Smith ierr = MatNullSpaceGetVecs(nullspace,&has_const,&n,&vecs);CHKERRQ(ierr); 240*1e07b27eSBarry Smith 241*1e07b27eSBarry Smith if (isActiveRank(sred->psubcomm)) { 242*1e07b27eSBarry Smith sub_vecs = NULL; 243*1e07b27eSBarry Smith /* create new vectors */ 244*1e07b27eSBarry Smith if (n != 0) { 245*1e07b27eSBarry Smith PetscMalloc(sizeof(Vec)*n,&sub_vecs); 246*1e07b27eSBarry Smith for (k=0; k<n; k++) { 247*1e07b27eSBarry Smith ierr = VecDuplicate(sred->xred,&sub_vecs[k]);CHKERRQ(ierr); 248*1e07b27eSBarry Smith } 249*1e07b27eSBarry Smith } 250*1e07b27eSBarry Smith } 251*1e07b27eSBarry Smith 252*1e07b27eSBarry Smith /* copy entries */ 253*1e07b27eSBarry Smith for (k=0; k<n; k++) { 254*1e07b27eSBarry Smith const PetscScalar *x_array; 255*1e07b27eSBarry Smith PetscScalar *LA_sub_vec; 256*1e07b27eSBarry Smith PetscInt st,ed,bs; 257*1e07b27eSBarry Smith 258*1e07b27eSBarry Smith /* pull in vector x->xtmp */ 259*1e07b27eSBarry Smith ierr = VecScatterBegin(sred->scatter,vecs[k],sred->xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 260*1e07b27eSBarry Smith ierr = VecScatterEnd(sred->scatter,vecs[k],sred->xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 261*1e07b27eSBarry Smith /* copy vector entires into xred */ 262*1e07b27eSBarry Smith ierr = VecGetBlockSize(sred->xtmp,&bs);CHKERRQ(ierr); 263*1e07b27eSBarry Smith ierr = VecGetArrayRead(sred->xtmp,&x_array);CHKERRQ(ierr); 264*1e07b27eSBarry Smith if (sub_vecs[k]) { 265*1e07b27eSBarry Smith ierr = VecGetOwnershipRange(sub_vecs[k],&st,&ed);CHKERRQ(ierr); 266*1e07b27eSBarry Smith ierr = VecGetArray(sub_vecs[k],&LA_sub_vec);CHKERRQ(ierr); 267*1e07b27eSBarry Smith for (i=0; i<ed-st; i++) { 268*1e07b27eSBarry Smith LA_sub_vec[i] = x_array[i]; 269*1e07b27eSBarry Smith } 270*1e07b27eSBarry Smith ierr = VecRestoreArray(sub_vecs[k],&LA_sub_vec);CHKERRQ(ierr); 271*1e07b27eSBarry Smith } 272*1e07b27eSBarry Smith ierr = VecRestoreArrayRead(sred->xtmp,&x_array);CHKERRQ(ierr); 273*1e07b27eSBarry Smith } 274*1e07b27eSBarry Smith 275*1e07b27eSBarry Smith if (isActiveRank(sred->psubcomm)) { 276*1e07b27eSBarry Smith /* create new nullspace for redundant object */ 277*1e07b27eSBarry Smith ierr = MatNullSpaceCreate(subcomm,has_const,n,sub_vecs,&sub_nullspace);CHKERRQ(ierr); 278*1e07b27eSBarry Smith /* attach redundant nullspace to Bred */ 279*1e07b27eSBarry Smith ierr = MatSetNullSpace(sub_mat,sub_nullspace);CHKERRQ(ierr); 280*1e07b27eSBarry Smith 281*1e07b27eSBarry Smith for (k=0; k<n; k++) { 282*1e07b27eSBarry Smith ierr = VecDestroy(&sub_vecs[k]);CHKERRQ(ierr); 283*1e07b27eSBarry Smith } 284*1e07b27eSBarry Smith if (sub_vecs) PetscFree(sub_vecs); 285*1e07b27eSBarry Smith } 286*1e07b27eSBarry Smith PetscFunctionReturn(0); 287*1e07b27eSBarry Smith } 288*1e07b27eSBarry Smith 289*1e07b27eSBarry Smith #undef __FUNCT__ 290*1e07b27eSBarry Smith #define __FUNCT__ "PCView_Telescope" 291*1e07b27eSBarry Smith static PetscErrorCode PCView_Telescope(PC pc,PetscViewer viewer) 292*1e07b27eSBarry Smith { 293*1e07b27eSBarry Smith PC_Telescope sred = (PC_Telescope)pc->data; 294*1e07b27eSBarry Smith PetscErrorCode ierr; 295*1e07b27eSBarry Smith PetscBool iascii,isstring; 296*1e07b27eSBarry Smith PetscViewer subviewer; 297*1e07b27eSBarry Smith 298*1e07b27eSBarry Smith PetscFunctionBegin; 299*1e07b27eSBarry Smith ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 300*1e07b27eSBarry Smith ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr); 301*1e07b27eSBarry Smith if (iascii) { 302*1e07b27eSBarry Smith if (!sred->psubcomm) { 303*1e07b27eSBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Telescope: preconditioner not yet setup\n");CHKERRQ(ierr); 304*1e07b27eSBarry Smith } else { 305*1e07b27eSBarry Smith MPI_Comm comm,subcomm; 306*1e07b27eSBarry Smith PetscMPIInt comm_size,subcomm_size; 307*1e07b27eSBarry Smith DM dm,subdm; 308*1e07b27eSBarry Smith 309*1e07b27eSBarry Smith ierr = PCGetDM(pc,&dm);CHKERRQ(ierr); 310*1e07b27eSBarry Smith subdm = private_PCTelescopeGetSubDM(sred); 311*1e07b27eSBarry Smith comm = PetscSubcommParent(sred->psubcomm); 312*1e07b27eSBarry Smith subcomm = PetscSubcommChild(sred->psubcomm); 313*1e07b27eSBarry Smith ierr = MPI_Comm_size(comm,&comm_size);CHKERRQ(ierr); 314*1e07b27eSBarry Smith ierr = MPI_Comm_size(subcomm,&subcomm_size);CHKERRQ(ierr); 315*1e07b27eSBarry Smith 316*1e07b27eSBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Telescope: parent comm size reduction factor = %D\n",sred->redfactor);CHKERRQ(ierr); 317*1e07b27eSBarry Smith ierr = PetscViewerASCIIPrintf(viewer," Telescope: comm_size = %d , subcomm_size = %d\n",(int)comm_size,(int)subcomm_size);CHKERRQ(ierr); 318*1e07b27eSBarry Smith ierr = PetscViewerGetSubViewer(viewer,subcomm,&subviewer);CHKERRQ(ierr); 319*1e07b27eSBarry Smith if (isActiveRank(sred->psubcomm)) { 320*1e07b27eSBarry Smith ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr); 321*1e07b27eSBarry Smith 322*1e07b27eSBarry Smith if (dm && sred->ignore_dm) { 323*1e07b27eSBarry Smith ierr = PetscViewerASCIIPrintf(subviewer," Telescope: ignoring DM\n");CHKERRQ(ierr); 324*1e07b27eSBarry Smith } 325*1e07b27eSBarry Smith switch (sred->sr_type) { 326*1e07b27eSBarry Smith case TELESCOPE_DEFAULT: 327*1e07b27eSBarry Smith ierr = PetscViewerASCIIPrintf(subviewer," Telescope: using default setup\n");CHKERRQ(ierr); 328*1e07b27eSBarry Smith break; 329*1e07b27eSBarry Smith case TELESCOPE_DMDA: 330*1e07b27eSBarry Smith ierr = PetscViewerASCIIPrintf(subviewer," Telescope: DMDA detected\n");CHKERRQ(ierr); 331*1e07b27eSBarry Smith ierr = DMView_DMDAShort(subdm,subviewer);CHKERRQ(ierr); 332*1e07b27eSBarry Smith break; 333*1e07b27eSBarry Smith case TELESCOPE_DMPLEX: 334*1e07b27eSBarry Smith ierr = PetscViewerASCIIPrintf(subviewer," Telescope: DMPLEX detected\n");CHKERRQ(ierr); 335*1e07b27eSBarry Smith break; 336*1e07b27eSBarry Smith } 337*1e07b27eSBarry Smith 338*1e07b27eSBarry Smith ierr = KSPView(sred->ksp,subviewer);CHKERRQ(ierr); 339*1e07b27eSBarry Smith ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr); 340*1e07b27eSBarry Smith } 341*1e07b27eSBarry Smith ierr = PetscViewerRestoreSubViewer(viewer,subcomm,&subviewer);CHKERRQ(ierr); 342*1e07b27eSBarry Smith } 343*1e07b27eSBarry Smith } 344*1e07b27eSBarry Smith PetscFunctionReturn(0); 345*1e07b27eSBarry Smith } 346*1e07b27eSBarry Smith 347*1e07b27eSBarry Smith #undef __FUNCT__ 348*1e07b27eSBarry Smith #define __FUNCT__ "PCSetUp_Telescope" 349*1e07b27eSBarry Smith static PetscErrorCode PCSetUp_Telescope(PC pc) 350*1e07b27eSBarry Smith { 351*1e07b27eSBarry Smith PC_Telescope sred = (PC_Telescope)pc->data; 352*1e07b27eSBarry Smith PetscErrorCode ierr; 353*1e07b27eSBarry Smith MPI_Comm comm,subcomm; 354*1e07b27eSBarry Smith PCTelescopeType sr_type; 355*1e07b27eSBarry Smith 356*1e07b27eSBarry Smith PetscFunctionBegin; 357*1e07b27eSBarry Smith ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr); 358*1e07b27eSBarry Smith 359*1e07b27eSBarry Smith /* subcomm definition */ 360*1e07b27eSBarry Smith if (!pc->setupcalled) { 361*1e07b27eSBarry Smith if (!sred->psubcomm) { 362*1e07b27eSBarry Smith ierr = PetscSubcommCreate(comm,&sred->psubcomm);CHKERRQ(ierr); 363*1e07b27eSBarry Smith ierr = PetscSubcommSetNumber(sred->psubcomm,sred->redfactor);CHKERRQ(ierr); 364*1e07b27eSBarry Smith ierr = PetscSubcommSetType(sred->psubcomm,PETSC_SUBCOMM_INTERLACED);CHKERRQ(ierr); 365*1e07b27eSBarry Smith /* disable runtime switch of psubcomm type, e.g., '-psubcomm_type interlaced */ 366*1e07b27eSBarry Smith /* ierr = PetscSubcommSetFromOptions(sred->psubcomm);CHKERRQ(ierr); */ 367*1e07b27eSBarry Smith ierr = PetscLogObjectMemory((PetscObject)pc,sizeof(PetscSubcomm));CHKERRQ(ierr); 368*1e07b27eSBarry Smith /* create a new PC that processors in each subcomm have copy of */ 369*1e07b27eSBarry Smith subcomm = PetscSubcommChild(sred->psubcomm); 370*1e07b27eSBarry Smith } 371*1e07b27eSBarry Smith } else { 372*1e07b27eSBarry Smith subcomm = PetscSubcommChild(sred->psubcomm); 373*1e07b27eSBarry Smith } 374*1e07b27eSBarry Smith 375*1e07b27eSBarry Smith /* internal KSP */ 376*1e07b27eSBarry Smith if (!pc->setupcalled) { 377*1e07b27eSBarry Smith const char *prefix; 378*1e07b27eSBarry Smith 379*1e07b27eSBarry Smith if (isActiveRank(sred->psubcomm)) { 380*1e07b27eSBarry Smith ierr = KSPCreate(subcomm,&sred->ksp);CHKERRQ(ierr); 381*1e07b27eSBarry Smith ierr = KSPSetErrorIfNotConverged(sred->ksp,pc->erroriffailure);CHKERRQ(ierr); 382*1e07b27eSBarry Smith ierr = PetscObjectIncrementTabLevel((PetscObject)sred->ksp,(PetscObject)pc,1);CHKERRQ(ierr); 383*1e07b27eSBarry Smith ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)sred->ksp);CHKERRQ(ierr); 384*1e07b27eSBarry Smith ierr = KSPSetType(sred->ksp,KSPPREONLY);CHKERRQ(ierr); 385*1e07b27eSBarry Smith ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr); 386*1e07b27eSBarry Smith ierr = KSPSetOptionsPrefix(sred->ksp,prefix);CHKERRQ(ierr); 387*1e07b27eSBarry Smith ierr = KSPAppendOptionsPrefix(sred->ksp,"telescope_");CHKERRQ(ierr); 388*1e07b27eSBarry Smith } 389*1e07b27eSBarry Smith } 390*1e07b27eSBarry Smith /* Determine type of setup/update */ 391*1e07b27eSBarry Smith if (!pc->setupcalled) { 392*1e07b27eSBarry Smith PetscBool has_dm,same; 393*1e07b27eSBarry Smith DM dm; 394*1e07b27eSBarry Smith 395*1e07b27eSBarry Smith sr_type = TELESCOPE_DEFAULT; 396*1e07b27eSBarry Smith has_dm = PETSC_FALSE; 397*1e07b27eSBarry Smith ierr = PCGetDM(pc,&dm);CHKERRQ(ierr); 398*1e07b27eSBarry Smith if (dm) { has_dm = PETSC_TRUE; } 399*1e07b27eSBarry Smith if (has_dm) { 400*1e07b27eSBarry Smith /* check for dmda */ 401*1e07b27eSBarry Smith ierr = PetscObjectTypeCompare((PetscObject)dm,DMDA,&same);CHKERRQ(ierr); 402*1e07b27eSBarry Smith if (same) { 403*1e07b27eSBarry Smith ierr = PetscInfo(pc,"PCTelescope: found DMDA\n");CHKERRQ(ierr); 404*1e07b27eSBarry Smith sr_type = TELESCOPE_DMDA; 405*1e07b27eSBarry Smith } 406*1e07b27eSBarry Smith /* check for dmplex */ 407*1e07b27eSBarry Smith ierr = PetscObjectTypeCompare((PetscObject)dm,DMPLEX,&same);CHKERRQ(ierr); 408*1e07b27eSBarry Smith if (same) { 409*1e07b27eSBarry Smith PetscInfo(pc,"PCTelescope: found DMPLEX\n"); 410*1e07b27eSBarry Smith sr_type = TELESCOPE_DMPLEX; 411*1e07b27eSBarry Smith } 412*1e07b27eSBarry Smith } 413*1e07b27eSBarry Smith 414*1e07b27eSBarry Smith if (sred->ignore_dm) { 415*1e07b27eSBarry Smith PetscInfo(pc,"PCTelescope: ignore DM\n"); 416*1e07b27eSBarry Smith sr_type = TELESCOPE_DEFAULT; 417*1e07b27eSBarry Smith } 418*1e07b27eSBarry Smith sred->sr_type = sr_type; 419*1e07b27eSBarry Smith } else { 420*1e07b27eSBarry Smith sr_type = sred->sr_type; 421*1e07b27eSBarry Smith } 422*1e07b27eSBarry Smith 423*1e07b27eSBarry Smith /* set function pointers for repartition setup, matrix creation/update, matrix nullspace and reset functionality */ 424*1e07b27eSBarry Smith switch (sr_type) { 425*1e07b27eSBarry Smith case TELESCOPE_DEFAULT: 426*1e07b27eSBarry Smith sred->pctelescope_setup_type = PCTelescopeSetUp_default; 427*1e07b27eSBarry Smith sred->pctelescope_matcreate_type = PCTelescopeMatCreate_default; 428*1e07b27eSBarry Smith sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_default; 429*1e07b27eSBarry Smith sred->pctelescope_reset_type = NULL; 430*1e07b27eSBarry Smith break; 431*1e07b27eSBarry Smith case TELESCOPE_DMDA: 432*1e07b27eSBarry Smith pc->ops->apply = PCApply_Telescope_dmda; 433*1e07b27eSBarry Smith sred->pctelescope_setup_type = PCTelescopeSetUp_dmda; 434*1e07b27eSBarry Smith sred->pctelescope_matcreate_type = PCTelescopeMatCreate_dmda; 435*1e07b27eSBarry Smith sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_dmda; 436*1e07b27eSBarry Smith sred->pctelescope_reset_type = PCReset_Telescope_dmda; 437*1e07b27eSBarry Smith break; 438*1e07b27eSBarry Smith case TELESCOPE_DMPLEX: SETERRQ(comm,PETSC_ERR_SUP,"Supprt for DMPLEX is currently not available"); 439*1e07b27eSBarry Smith break; 440*1e07b27eSBarry Smith default: SETERRQ(comm,PETSC_ERR_SUP,"Only supprt for repartitioning DMDA is provided"); 441*1e07b27eSBarry Smith break; 442*1e07b27eSBarry Smith } 443*1e07b27eSBarry Smith 444*1e07b27eSBarry Smith /* setup */ 445*1e07b27eSBarry Smith if (sred->pctelescope_setup_type) { 446*1e07b27eSBarry Smith ierr = sred->pctelescope_setup_type(pc,sred);CHKERRQ(ierr); 447*1e07b27eSBarry Smith } 448*1e07b27eSBarry Smith /* update */ 449*1e07b27eSBarry Smith if (!pc->setupcalled) { 450*1e07b27eSBarry Smith if (sred->pctelescope_matcreate_type) { 451*1e07b27eSBarry Smith ierr = sred->pctelescope_matcreate_type(pc,sred,MAT_INITIAL_MATRIX,&sred->Bred);CHKERRQ(ierr); 452*1e07b27eSBarry Smith } 453*1e07b27eSBarry Smith if (sred->pctelescope_matnullspacecreate_type) { 454*1e07b27eSBarry Smith ierr = sred->pctelescope_matnullspacecreate_type(pc,sred,sred->Bred);CHKERRQ(ierr); 455*1e07b27eSBarry Smith } 456*1e07b27eSBarry Smith } else { 457*1e07b27eSBarry Smith if (sred->pctelescope_matcreate_type) { 458*1e07b27eSBarry Smith ierr = sred->pctelescope_matcreate_type(pc,sred,MAT_REUSE_MATRIX,&sred->Bred);CHKERRQ(ierr); 459*1e07b27eSBarry Smith } 460*1e07b27eSBarry Smith } 461*1e07b27eSBarry Smith 462*1e07b27eSBarry Smith /* common - no construction */ 463*1e07b27eSBarry Smith if (isActiveRank(sred->psubcomm)) { 464*1e07b27eSBarry Smith ierr = KSPSetOperators(sred->ksp,sred->Bred,sred->Bred);CHKERRQ(ierr); 465*1e07b27eSBarry Smith if (pc->setfromoptionscalled && !pc->setupcalled){ 466*1e07b27eSBarry Smith ierr = KSPSetFromOptions(sred->ksp);CHKERRQ(ierr); 467*1e07b27eSBarry Smith } 468*1e07b27eSBarry Smith } 469*1e07b27eSBarry Smith PetscFunctionReturn(0); 470*1e07b27eSBarry Smith } 471*1e07b27eSBarry Smith 472*1e07b27eSBarry Smith #undef __FUNCT__ 473*1e07b27eSBarry Smith #define __FUNCT__ "PCApply_Telescope" 474*1e07b27eSBarry Smith static PetscErrorCode PCApply_Telescope(PC pc,Vec x,Vec y) 475*1e07b27eSBarry Smith { 476*1e07b27eSBarry Smith PC_Telescope sred = (PC_Telescope)pc->data; 477*1e07b27eSBarry Smith PetscErrorCode ierr; 478*1e07b27eSBarry Smith Vec xtmp,xred,yred; 479*1e07b27eSBarry Smith PetscInt i,st,ed,bs; 480*1e07b27eSBarry Smith VecScatter scatter; 481*1e07b27eSBarry Smith PetscScalar *array; 482*1e07b27eSBarry Smith const PetscScalar *x_array; 483*1e07b27eSBarry Smith 484*1e07b27eSBarry Smith PetscFunctionBegin; 485*1e07b27eSBarry Smith xtmp = sred->xtmp; 486*1e07b27eSBarry Smith scatter = sred->scatter; 487*1e07b27eSBarry Smith xred = sred->xred; 488*1e07b27eSBarry Smith yred = sred->yred; 489*1e07b27eSBarry Smith 490*1e07b27eSBarry Smith /* pull in vector x->xtmp */ 491*1e07b27eSBarry Smith ierr = VecScatterBegin(scatter,x,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 492*1e07b27eSBarry Smith ierr = VecScatterEnd(scatter,x,xtmp,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 493*1e07b27eSBarry Smith 494*1e07b27eSBarry Smith /* copy vector entires into xred */ 495*1e07b27eSBarry Smith ierr = VecGetBlockSize(xtmp,&bs);CHKERRQ(ierr); 496*1e07b27eSBarry Smith ierr = VecGetArrayRead(xtmp,&x_array);CHKERRQ(ierr); 497*1e07b27eSBarry Smith if (xred) { 498*1e07b27eSBarry Smith PetscScalar *LA_xred; 499*1e07b27eSBarry Smith ierr = VecGetOwnershipRange(xred,&st,&ed);CHKERRQ(ierr); 500*1e07b27eSBarry Smith ierr = VecGetArray(xred,&LA_xred);CHKERRQ(ierr); 501*1e07b27eSBarry Smith for (i=0; i<ed-st; i++) { 502*1e07b27eSBarry Smith LA_xred[i] = x_array[i]; 503*1e07b27eSBarry Smith } 504*1e07b27eSBarry Smith ierr = VecRestoreArray(xred,&LA_xred);CHKERRQ(ierr); 505*1e07b27eSBarry Smith } 506*1e07b27eSBarry Smith ierr = VecRestoreArrayRead(xtmp,&x_array);CHKERRQ(ierr); 507*1e07b27eSBarry Smith /* solve */ 508*1e07b27eSBarry Smith if (isActiveRank(sred->psubcomm)) { 509*1e07b27eSBarry Smith ierr = KSPSolve(sred->ksp,xred,yred);CHKERRQ(ierr); 510*1e07b27eSBarry Smith } 511*1e07b27eSBarry Smith /* return vector */ 512*1e07b27eSBarry Smith ierr = VecGetBlockSize(xtmp,&bs);CHKERRQ(ierr); 513*1e07b27eSBarry Smith ierr = VecGetArray(xtmp,&array);CHKERRQ(ierr); 514*1e07b27eSBarry Smith if (yred) { 515*1e07b27eSBarry Smith const PetscScalar *LA_yred; 516*1e07b27eSBarry Smith ierr = VecGetOwnershipRange(yred,&st,&ed);CHKERRQ(ierr); 517*1e07b27eSBarry Smith ierr = VecGetArrayRead(yred,&LA_yred);CHKERRQ(ierr); 518*1e07b27eSBarry Smith for (i=0; i<ed-st; i++) { 519*1e07b27eSBarry Smith array[i] = LA_yred[i]; 520*1e07b27eSBarry Smith } 521*1e07b27eSBarry Smith ierr = VecRestoreArrayRead(yred,&LA_yred);CHKERRQ(ierr); 522*1e07b27eSBarry Smith } else { 523*1e07b27eSBarry Smith for (i=0; i<bs; i++) { 524*1e07b27eSBarry Smith array[i] = 0.0; 525*1e07b27eSBarry Smith } 526*1e07b27eSBarry Smith } 527*1e07b27eSBarry Smith ierr = VecRestoreArray(xtmp,&array);CHKERRQ(ierr); 528*1e07b27eSBarry Smith ierr = VecScatterBegin(scatter,xtmp,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 529*1e07b27eSBarry Smith ierr = VecScatterEnd(scatter,xtmp,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 530*1e07b27eSBarry Smith PetscFunctionReturn(0); 531*1e07b27eSBarry Smith } 532*1e07b27eSBarry Smith 533*1e07b27eSBarry Smith #undef __FUNCT__ 534*1e07b27eSBarry Smith #define __FUNCT__ "PCReset_Telescope" 535*1e07b27eSBarry Smith static PetscErrorCode PCReset_Telescope(PC pc) 536*1e07b27eSBarry Smith { 537*1e07b27eSBarry Smith PC_Telescope sred = (PC_Telescope)pc->data; 538*1e07b27eSBarry Smith PetscErrorCode ierr; 539*1e07b27eSBarry Smith 540*1e07b27eSBarry Smith ierr = ISDestroy(&sred->isin);CHKERRQ(ierr); 541*1e07b27eSBarry Smith ierr = VecScatterDestroy(&sred->scatter);CHKERRQ(ierr); 542*1e07b27eSBarry Smith if (sred->xred) { ierr = VecDestroy(&sred->xred);CHKERRQ(ierr); } 543*1e07b27eSBarry Smith if (sred->yred) { ierr = VecDestroy(&sred->yred);CHKERRQ(ierr); } 544*1e07b27eSBarry Smith if (sred->xtmp) { ierr = VecDestroy(&sred->xtmp);CHKERRQ(ierr); } 545*1e07b27eSBarry Smith if (sred->Bred) { ierr = MatDestroy(&sred->Bred);CHKERRQ(ierr); } 546*1e07b27eSBarry Smith if (sred->ksp) { ierr = KSPReset(sred->ksp);CHKERRQ(ierr); } 547*1e07b27eSBarry Smith if (sred->pctelescope_reset_type) { 548*1e07b27eSBarry Smith ierr = sred->pctelescope_reset_type(pc);CHKERRQ(ierr); 549*1e07b27eSBarry Smith } 550*1e07b27eSBarry Smith PetscFunctionReturn(0); 551*1e07b27eSBarry Smith } 552*1e07b27eSBarry Smith 553*1e07b27eSBarry Smith #undef __FUNCT__ 554*1e07b27eSBarry Smith #define __FUNCT__ "PCDestroy_Telescope" 555*1e07b27eSBarry Smith static PetscErrorCode PCDestroy_Telescope(PC pc) 556*1e07b27eSBarry Smith { 557*1e07b27eSBarry Smith PC_Telescope sred = (PC_Telescope)pc->data; 558*1e07b27eSBarry Smith PetscErrorCode ierr; 559*1e07b27eSBarry Smith 560*1e07b27eSBarry Smith PetscFunctionBegin; 561*1e07b27eSBarry Smith ierr = PCReset_Telescope(pc);CHKERRQ(ierr); 562*1e07b27eSBarry Smith if (sred->ksp) { ierr = KSPDestroy(&sred->ksp);CHKERRQ(ierr); } 563*1e07b27eSBarry Smith ierr = PetscSubcommDestroy(&sred->psubcomm);CHKERRQ(ierr); 564*1e07b27eSBarry Smith if (sred->dm_ctx) PetscFree(sred->dm_ctx); 565*1e07b27eSBarry Smith PetscFree(pc->data); 566*1e07b27eSBarry Smith PetscFunctionReturn(0); 567*1e07b27eSBarry Smith } 568*1e07b27eSBarry Smith 569*1e07b27eSBarry Smith #undef __FUNCT__ 570*1e07b27eSBarry Smith #define __FUNCT__ "PCSetFromOptions_Telescope" 571*1e07b27eSBarry Smith static PetscErrorCode PCSetFromOptions_Telescope(PetscOptions *PetscOptionsObject,PC pc) 572*1e07b27eSBarry Smith { 573*1e07b27eSBarry Smith PC_Telescope sred = (PC_Telescope)pc->data; 574*1e07b27eSBarry Smith PetscErrorCode ierr; 575*1e07b27eSBarry Smith MPI_Comm comm; 576*1e07b27eSBarry Smith PetscMPIInt size; 577*1e07b27eSBarry Smith 578*1e07b27eSBarry Smith PetscFunctionBegin; 579*1e07b27eSBarry Smith ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr); 580*1e07b27eSBarry Smith ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 581*1e07b27eSBarry Smith ierr = PetscOptionsHead(PetscOptionsObject,"Telescope options");CHKERRQ(ierr); 582*1e07b27eSBarry Smith ierr = PetscOptionsInt("-pc_telescope_reduction_factor","Factor to reduce comm size by","PCTelescopeSetReductionFactor",sred->redfactor,&sred->redfactor,0);CHKERRQ(ierr); 583*1e07b27eSBarry Smith if (sred->redfactor > size) SETERRQ(comm,PETSC_ERR_ARG_WRONG,"-pc_telescope_reduction_factor <= comm size"); 584*1e07b27eSBarry Smith ierr = PetscOptionsBool("-pc_telescope_ignore_dm","Ignore any DM attached to the PC","PCTelescopeSetIgnoreDM",sred->ignore_dm,&sred->ignore_dm,0);CHKERRQ(ierr); 585*1e07b27eSBarry Smith ierr = PetscOptionsTail();CHKERRQ(ierr); 586*1e07b27eSBarry Smith PetscFunctionReturn(0); 587*1e07b27eSBarry Smith } 588*1e07b27eSBarry Smith 589*1e07b27eSBarry Smith /* PC simplementation specific API's */ 590*1e07b27eSBarry Smith 591*1e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetKSP_Telescope(PC pc,KSP *ksp) 592*1e07b27eSBarry Smith { 593*1e07b27eSBarry Smith PC_Telescope red = (PC_Telescope)pc->data; 594*1e07b27eSBarry Smith if (ksp) *ksp = red->ksp; 595*1e07b27eSBarry Smith return(0); 596*1e07b27eSBarry Smith } 597*1e07b27eSBarry Smith 598*1e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetReductionFactor_Telescope(PC pc,PetscInt *fact) 599*1e07b27eSBarry Smith { 600*1e07b27eSBarry Smith PC_Telescope red = (PC_Telescope)pc->data; 601*1e07b27eSBarry Smith if (fact) *fact = red->redfactor; 602*1e07b27eSBarry Smith return(0); 603*1e07b27eSBarry Smith } 604*1e07b27eSBarry Smith 605*1e07b27eSBarry Smith static PetscErrorCode PCTelescopeSetReductionFactor_Telescope(PC pc,PetscInt fact) 606*1e07b27eSBarry Smith { 607*1e07b27eSBarry Smith PC_Telescope red = (PC_Telescope)pc->data; 608*1e07b27eSBarry Smith PetscMPIInt size; 609*1e07b27eSBarry Smith PetscErrorCode ierr; 610*1e07b27eSBarry Smith 611*1e07b27eSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr); 612*1e07b27eSBarry Smith if (fact <= 0) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Reduction factor of telescoping PC %D must be positive",fact); 613*1e07b27eSBarry Smith if (fact > size) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Reduction factor of telescoping PC %D must be <= comm.size",fact); 614*1e07b27eSBarry Smith red->redfactor = fact; 615*1e07b27eSBarry Smith return(0); 616*1e07b27eSBarry Smith } 617*1e07b27eSBarry Smith 618*1e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetIgnoreDM_Telescope(PC pc,PetscBool *v) 619*1e07b27eSBarry Smith { 620*1e07b27eSBarry Smith PC_Telescope red = (PC_Telescope)pc->data; 621*1e07b27eSBarry Smith if (v) *v = red->ignore_dm; 622*1e07b27eSBarry Smith return(0); 623*1e07b27eSBarry Smith } 624*1e07b27eSBarry Smith static PetscErrorCode PCTelescopeSetIgnoreDM_Telescope(PC pc,PetscBool v) 625*1e07b27eSBarry Smith { 626*1e07b27eSBarry Smith PC_Telescope red = (PC_Telescope)pc->data; 627*1e07b27eSBarry Smith red->ignore_dm = v; 628*1e07b27eSBarry Smith return(0); 629*1e07b27eSBarry Smith } 630*1e07b27eSBarry Smith 631*1e07b27eSBarry Smith static PetscErrorCode PCTelescopeGetDM_Telescope(PC pc,DM *dm) 632*1e07b27eSBarry Smith { 633*1e07b27eSBarry Smith PC_Telescope red = (PC_Telescope)pc->data; 634*1e07b27eSBarry Smith *dm = private_PCTelescopeGetSubDM(red); 635*1e07b27eSBarry Smith return(0); 636*1e07b27eSBarry Smith } 637*1e07b27eSBarry Smith 638*1e07b27eSBarry Smith /*@ 639*1e07b27eSBarry Smith PCTelescopeGetKSP - Gets the KSP created by the telescoping PC. 640*1e07b27eSBarry Smith 641*1e07b27eSBarry Smith Not Collective 642*1e07b27eSBarry Smith 643*1e07b27eSBarry Smith Input Parameter: 644*1e07b27eSBarry Smith . pc - the preconditioner context 645*1e07b27eSBarry Smith 646*1e07b27eSBarry Smith Output Parameter: 647*1e07b27eSBarry Smith . subksp - the KSP defined the smaller set of processes 648*1e07b27eSBarry Smith 649*1e07b27eSBarry Smith Level: advanced 650*1e07b27eSBarry Smith 651*1e07b27eSBarry Smith .keywords: PC, telescopting solve 652*1e07b27eSBarry Smith @*/ 653*1e07b27eSBarry Smith PetscErrorCode PCTelescopeGetKSP(PC pc,KSP *subksp) 654*1e07b27eSBarry Smith { 655*1e07b27eSBarry Smith PetscTryMethod(pc,"PCTelescopeGetKSP_C",(PC,KSP*),(pc,subksp)); 656*1e07b27eSBarry Smith return(0); 657*1e07b27eSBarry Smith } 658*1e07b27eSBarry Smith 659*1e07b27eSBarry Smith /*@ 660*1e07b27eSBarry Smith PCTelescopeGetReductionFactor - Gets the factor by which the original number of processes has been reduced by. 661*1e07b27eSBarry Smith 662*1e07b27eSBarry Smith Not Collective 663*1e07b27eSBarry Smith 664*1e07b27eSBarry Smith Input Parameter: 665*1e07b27eSBarry Smith . pc - the preconditioner context 666*1e07b27eSBarry Smith 667*1e07b27eSBarry Smith Output Parameter: 668*1e07b27eSBarry Smith . fact - the reduction factor 669*1e07b27eSBarry Smith 670*1e07b27eSBarry Smith Level: advanced 671*1e07b27eSBarry Smith 672*1e07b27eSBarry Smith .keywords: PC, telescoping solve 673*1e07b27eSBarry Smith @*/ 674*1e07b27eSBarry Smith PetscErrorCode PCTelescopeGetReductionFactor(PC pc,PetscInt *fact) 675*1e07b27eSBarry Smith { 676*1e07b27eSBarry Smith PetscTryMethod(pc,"PCTelescopeGetReductionFactor_C",(PC,PetscInt*),(pc,fact)); 677*1e07b27eSBarry Smith return(0); 678*1e07b27eSBarry Smith } 679*1e07b27eSBarry Smith 680*1e07b27eSBarry Smith /*@ 681*1e07b27eSBarry Smith PCTelescopeSetReductionFactor - Sets the factor by which the original number of processes has been reduced by. 682*1e07b27eSBarry Smith 683*1e07b27eSBarry Smith Not Collective 684*1e07b27eSBarry Smith 685*1e07b27eSBarry Smith Input Parameter: 686*1e07b27eSBarry Smith . pc - the preconditioner context 687*1e07b27eSBarry Smith 688*1e07b27eSBarry Smith Output Parameter: 689*1e07b27eSBarry Smith . fact - the reduction factor 690*1e07b27eSBarry Smith 691*1e07b27eSBarry Smith Level: advanced 692*1e07b27eSBarry Smith 693*1e07b27eSBarry Smith .keywords: PC, telescoping solve 694*1e07b27eSBarry Smith @*/ 695*1e07b27eSBarry Smith PetscErrorCode PCTelescopeSetReductionFactor(PC pc,PetscInt fact) 696*1e07b27eSBarry Smith { 697*1e07b27eSBarry Smith PetscTryMethod(pc,"PCTelescopeSetReductionFactor_C",(PC,PetscInt),(pc,fact)); 698*1e07b27eSBarry Smith return(0); 699*1e07b27eSBarry Smith } 700*1e07b27eSBarry Smith 701*1e07b27eSBarry Smith /*@ 702*1e07b27eSBarry Smith PCTelescopeGetIgnoreDM - Get the flag indicating if any DM attached to the PC will be used. 703*1e07b27eSBarry Smith 704*1e07b27eSBarry Smith Not Collective 705*1e07b27eSBarry Smith 706*1e07b27eSBarry Smith Input Parameter: 707*1e07b27eSBarry Smith . pc - the preconditioner context 708*1e07b27eSBarry Smith 709*1e07b27eSBarry Smith Output Parameter: 710*1e07b27eSBarry Smith . v - the flag 711*1e07b27eSBarry Smith 712*1e07b27eSBarry Smith Level: advanced 713*1e07b27eSBarry Smith 714*1e07b27eSBarry Smith .keywords: PC, telescoping solve 715*1e07b27eSBarry Smith @*/ 716*1e07b27eSBarry Smith PetscErrorCode PCTelescopeGetIgnoreDM(PC pc,PetscBool *v) 717*1e07b27eSBarry Smith { 718*1e07b27eSBarry Smith PetscTryMethod(pc,"PCTelescopeGetIgnoreDM_C",(PC,PetscBool*),(pc,v)); 719*1e07b27eSBarry Smith return(0); 720*1e07b27eSBarry Smith } 721*1e07b27eSBarry Smith 722*1e07b27eSBarry Smith /*@ 723*1e07b27eSBarry Smith PCTelescopeSetIgnoreDM - Set a flag to ignore any DM attached to the PC. 724*1e07b27eSBarry Smith 725*1e07b27eSBarry Smith Not Collective 726*1e07b27eSBarry Smith 727*1e07b27eSBarry Smith Input Parameter: 728*1e07b27eSBarry Smith . pc - the preconditioner context 729*1e07b27eSBarry Smith 730*1e07b27eSBarry Smith Output Parameter: 731*1e07b27eSBarry Smith . v - Use PETSC_TRUE to ignore any DM 732*1e07b27eSBarry Smith 733*1e07b27eSBarry Smith Level: advanced 734*1e07b27eSBarry Smith 735*1e07b27eSBarry Smith .keywords: PC, telescoping solve 736*1e07b27eSBarry Smith @*/ 737*1e07b27eSBarry Smith PetscErrorCode PCTelescopeSetIgnoreDM(PC pc,PetscInt v) 738*1e07b27eSBarry Smith { 739*1e07b27eSBarry Smith PetscTryMethod(pc,"PCTelescopeSetIgnoreDM_C",(PC,PetscBool),(pc,v)); 740*1e07b27eSBarry Smith return(0); 741*1e07b27eSBarry Smith } 742*1e07b27eSBarry Smith 743*1e07b27eSBarry Smith /*@ 744*1e07b27eSBarry Smith PCTelescopeGetDM - Get the re-partitioned DM attached to the sub KSP. 745*1e07b27eSBarry Smith 746*1e07b27eSBarry Smith Not Collective 747*1e07b27eSBarry Smith 748*1e07b27eSBarry Smith Input Parameter: 749*1e07b27eSBarry Smith . pc - the preconditioner context 750*1e07b27eSBarry Smith 751*1e07b27eSBarry Smith Output Parameter: 752*1e07b27eSBarry Smith . subdm - The re-partitioned DM 753*1e07b27eSBarry Smith 754*1e07b27eSBarry Smith Level: advanced 755*1e07b27eSBarry Smith 756*1e07b27eSBarry Smith .keywords: PC, telescoping solve 757*1e07b27eSBarry Smith @*/ 758*1e07b27eSBarry Smith PetscErrorCode PCTelescopeGetDM(PC pc,DM *subdm) 759*1e07b27eSBarry Smith { 760*1e07b27eSBarry Smith PetscTryMethod(pc,"PCTelescopeGetDM_C",(PC,DM*),(pc,subdm)); 761*1e07b27eSBarry Smith return(0); 762*1e07b27eSBarry Smith } 763*1e07b27eSBarry Smith 764*1e07b27eSBarry Smith /* -------------------------------------------------------------------------------------*/ 765*1e07b27eSBarry Smith /*MC 766*1e07b27eSBarry Smith PCTELESCOPE - Runs a KSP solver on a sub-group of processors. MPI processes not in the sub-communicator are idle during the solve. 767*1e07b27eSBarry Smith 768*1e07b27eSBarry Smith Options Database: 769*1e07b27eSBarry Smith + -pc_telescope_reduction_factor <n> - factor to use communicator size by, for example if you are using 64 MPI processes and 770*1e07b27eSBarry Smith use an n of 4, the new sub-communicator will be 4 defined with 64/4 processes 771*1e07b27eSBarry Smith - -pc_telescope_ignore_dm <false> - flag to indicate whether an attached DM should be ignored 772*1e07b27eSBarry Smith 773*1e07b27eSBarry Smith Level: advanced 774*1e07b27eSBarry Smith 775*1e07b27eSBarry Smith Notes: 776*1e07b27eSBarry Smith The default KSP is PREONLY. If a DM is attached to the PC, it is re-partitioned on the sub-communicator. 777*1e07b27eSBarry 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. 778*1e07b27eSBarry Smith Currently only support for re-partitioning a DMDA is provided. 779*1e07b27eSBarry Smith Any nullspace attached to the original Bmat operator are extracted, re-partitioned and set on the repartitioned Bmat operator. 780*1e07b27eSBarry Smith KSPSetComputeOperators() is not propagated to the sub KSP. 781*1e07b27eSBarry Smith Currently there is no support for the flag -pc_use_amat 782*1e07b27eSBarry Smith 783*1e07b27eSBarry Smith Optimizations: 784*1e07b27eSBarry Smith (i) VecPlaceArray() could be used for scatters between the vectors defined on different sized communicators, thereby slightly reducing memory footprint; 785*1e07b27eSBarry Smith (ii) Memory re-use and faster set-up would follow if the result of P^T.A.P was not re-allocated each time PCSetUp_Telescope() was called (DMDA). 786*1e07b27eSBarry Smith 787*1e07b27eSBarry Smith Contributed by Dave May 788*1e07b27eSBarry Smith 789*1e07b27eSBarry Smith .seealso: PCTelescopeGetKSP(), PCTelescopeGetDM(), 790*1e07b27eSBarry Smith PCTelescopeGetReductionFactor(), PCTelescopeSetReductionFactor(), 791*1e07b27eSBarry Smith PCTelescopeGetIgnoreDM(), PCTelescopeSetIgnoreDM(), PCREDUNDANT 792*1e07b27eSBarry Smith M*/ 793*1e07b27eSBarry Smith #undef __FUNCT__ 794*1e07b27eSBarry Smith #define __FUNCT__ "PCCreate_Telescope" 795*1e07b27eSBarry Smith PETSC_EXTERN PetscErrorCode PCCreate_Telescope(PC pc) 796*1e07b27eSBarry Smith { 797*1e07b27eSBarry Smith PetscErrorCode ierr; 798*1e07b27eSBarry Smith struct _PC_Telescope *sred; 799*1e07b27eSBarry Smith 800*1e07b27eSBarry Smith PetscFunctionBegin; 801*1e07b27eSBarry Smith ierr = PetscNewLog(pc,&sred);CHKERRQ(ierr); 802*1e07b27eSBarry Smith sred->redfactor = 1; 803*1e07b27eSBarry Smith sred->ignore_dm = PETSC_FALSE; 804*1e07b27eSBarry Smith pc->data = (void*)sred; 805*1e07b27eSBarry Smith 806*1e07b27eSBarry Smith pc->ops->apply = PCApply_Telescope; 807*1e07b27eSBarry Smith pc->ops->applytranspose = NULL; 808*1e07b27eSBarry Smith pc->ops->setup = PCSetUp_Telescope; 809*1e07b27eSBarry Smith pc->ops->destroy = PCDestroy_Telescope; 810*1e07b27eSBarry Smith pc->ops->reset = PCReset_Telescope; 811*1e07b27eSBarry Smith pc->ops->setfromoptions = PCSetFromOptions_Telescope; 812*1e07b27eSBarry Smith pc->ops->view = PCView_Telescope; 813*1e07b27eSBarry Smith 814*1e07b27eSBarry Smith sred->pctelescope_setup_type = PCTelescopeSetUp_default; 815*1e07b27eSBarry Smith sred->pctelescope_matcreate_type = PCTelescopeMatCreate_default; 816*1e07b27eSBarry Smith sred->pctelescope_matnullspacecreate_type = PCTelescopeMatNullSpaceCreate_default; 817*1e07b27eSBarry Smith sred->pctelescope_reset_type = NULL; 818*1e07b27eSBarry Smith 819*1e07b27eSBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetKSP_C",PCTelescopeGetKSP_Telescope);CHKERRQ(ierr); 820*1e07b27eSBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetReductionFactor_C",PCTelescopeGetReductionFactor_Telescope);CHKERRQ(ierr); 821*1e07b27eSBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetReductionFactor_C",PCTelescopeSetReductionFactor_Telescope);CHKERRQ(ierr); 822*1e07b27eSBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetIgnoreDM_C",PCTelescopeGetIgnoreDM_Telescope);CHKERRQ(ierr); 823*1e07b27eSBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeSetIgnoreDM_C",PCTelescopeSetIgnoreDM_Telescope);CHKERRQ(ierr); 824*1e07b27eSBarry Smith ierr = PetscObjectComposeFunction((PetscObject)pc,"PCTelescopeGetDM_C",PCTelescopeGetDM_Telescope);CHKERRQ(ierr); 825*1e07b27eSBarry Smith PetscFunctionReturn(0); 826*1e07b27eSBarry Smith } 827