xref: /petsc/src/ksp/pc/impls/telescope/telescope_dmda.c (revision 28b400f66ebc7ae0049166a2294dfcd3df27e64b)
11e07b27eSBarry Smith 
2120bdd93SDave May #include <petsc/private/matimpl.h>
31e07b27eSBarry Smith #include <petsc/private/pcimpl.h>
45e897e82SDave May #include <petsc/private/dmimpl.h>
51e07b27eSBarry Smith #include <petscksp.h>           /*I "petscksp.h" I*/
61e07b27eSBarry Smith #include <petscdm.h>
71e07b27eSBarry Smith #include <petscdmda.h>
81e07b27eSBarry Smith 
9575a0592SBarry Smith #include "../src/ksp/pc/impls/telescope/telescope.h"
101e07b27eSBarry Smith 
11bf00f589SPatrick Sanan static PetscBool  cited = PETSC_FALSE;
12bf00f589SPatrick Sanan static const char citation[] =
13bf00f589SPatrick Sanan "@inproceedings{MaySananRuppKnepleySmith2016,\n"
14bf00f589SPatrick Sanan "  title     = {Extreme-Scale Multigrid Components within PETSc},\n"
15bf00f589SPatrick Sanan "  author    = {Dave A. May and Patrick Sanan and Karl Rupp and Matthew G. Knepley and Barry F. Smith},\n"
16bf00f589SPatrick Sanan "  booktitle = {Proceedings of the Platform for Advanced Scientific Computing Conference},\n"
17bf00f589SPatrick Sanan "  series    = {PASC '16},\n"
18bf00f589SPatrick Sanan "  isbn      = {978-1-4503-4126-4},\n"
19bf00f589SPatrick Sanan "  location  = {Lausanne, Switzerland},\n"
20bf00f589SPatrick Sanan "  pages     = {5:1--5:12},\n"
21bf00f589SPatrick Sanan "  articleno = {5},\n"
22bf00f589SPatrick Sanan "  numpages  = {12},\n"
23a8d69d7bSBarry Smith "  url       = {https://doi.acm.org/10.1145/2929908.2929913},\n"
24bf00f589SPatrick Sanan "  doi       = {10.1145/2929908.2929913},\n"
25bf00f589SPatrick Sanan "  acmid     = {2929913},\n"
26bf00f589SPatrick Sanan "  publisher = {ACM},\n"
27bf00f589SPatrick Sanan "  address   = {New York, NY, USA},\n"
28bf00f589SPatrick Sanan "  keywords  = {GPU, HPC, agglomeration, coarse-level solver, multigrid, parallel computing, preconditioning},\n"
29bf00f589SPatrick Sanan "  year      = {2016}\n"
30bf00f589SPatrick Sanan "}\n";
31bf00f589SPatrick Sanan 
3257f12427SDave May static PetscErrorCode _DMDADetermineRankFromGlobalIJK(PetscInt dim,PetscInt i,PetscInt j,PetscInt k,
331e07b27eSBarry Smith                                                       PetscInt Mp,PetscInt Np,PetscInt Pp,
341e07b27eSBarry Smith                                                       PetscInt start_i[],PetscInt start_j[],PetscInt start_k[],
351e07b27eSBarry Smith                                                       PetscInt span_i[],PetscInt span_j[],PetscInt span_k[],
361e07b27eSBarry Smith                                                       PetscMPIInt *_pi,PetscMPIInt *_pj,PetscMPIInt *_pk,PetscMPIInt *rank_re)
371e07b27eSBarry Smith {
381e07b27eSBarry Smith   PetscInt pi,pj,pk,n;
391e07b27eSBarry Smith 
401e07b27eSBarry Smith   PetscFunctionBegin;
41137d0469SJed Brown   *rank_re = -1;
42137d0469SJed Brown   if (_pi) *_pi = -1;
43137d0469SJed Brown   if (_pj) *_pj = -1;
44137d0469SJed Brown   if (_pk) *_pk = -1;
451e07b27eSBarry Smith   pi = pj = pk = -1;
461e07b27eSBarry Smith   if (_pi) {
471e07b27eSBarry Smith     for (n=0; n<Mp; n++) {
481e07b27eSBarry Smith       if ((i >= start_i[n]) && (i < start_i[n]+span_i[n])) {
491e07b27eSBarry Smith         pi = n;
501e07b27eSBarry Smith         break;
511e07b27eSBarry Smith       }
521e07b27eSBarry Smith     }
532c71b3e2SJacob Faibussowitsch     PetscCheckFalse(pi == -1,PETSC_COMM_SELF,PETSC_ERR_USER,"[dmda-ijk] pi cannot be determined : range %D, val %D",Mp,i);
541e07b27eSBarry Smith     *_pi = pi;
551e07b27eSBarry Smith   }
561e07b27eSBarry Smith 
571e07b27eSBarry Smith   if (_pj) {
581e07b27eSBarry Smith     for (n=0; n<Np; n++) {
591e07b27eSBarry Smith       if ((j >= start_j[n]) && (j < start_j[n]+span_j[n])) {
601e07b27eSBarry Smith         pj = n;
611e07b27eSBarry Smith         break;
621e07b27eSBarry Smith       }
631e07b27eSBarry Smith     }
642c71b3e2SJacob Faibussowitsch     PetscCheckFalse(pj == -1,PETSC_COMM_SELF,PETSC_ERR_USER,"[dmda-ijk] pj cannot be determined : range %D, val %D",Np,j);
651e07b27eSBarry Smith     *_pj = pj;
661e07b27eSBarry Smith   }
671e07b27eSBarry Smith 
681e07b27eSBarry Smith   if (_pk) {
691e07b27eSBarry Smith     for (n=0; n<Pp; n++) {
701e07b27eSBarry Smith       if ((k >= start_k[n]) && (k < start_k[n]+span_k[n])) {
711e07b27eSBarry Smith         pk = n;
721e07b27eSBarry Smith         break;
731e07b27eSBarry Smith       }
741e07b27eSBarry Smith     }
752c71b3e2SJacob Faibussowitsch     PetscCheckFalse(pk == -1,PETSC_COMM_SELF,PETSC_ERR_USER,"[dmda-ijk] pk cannot be determined : range %D, val %D",Pp,k);
761e07b27eSBarry Smith     *_pk = pk;
771e07b27eSBarry Smith   }
781e07b27eSBarry Smith 
791e07b27eSBarry Smith   switch (dim) {
801e07b27eSBarry Smith   case 1:
811e07b27eSBarry Smith     *rank_re = pi;
821e07b27eSBarry Smith     break;
831e07b27eSBarry Smith   case 2:
841e07b27eSBarry Smith     *rank_re = pi + pj * Mp;
851e07b27eSBarry Smith     break;
861e07b27eSBarry Smith   case 3:
871e07b27eSBarry Smith     *rank_re = pi + pj * Mp + pk * (Mp*Np);
881e07b27eSBarry Smith     break;
891e07b27eSBarry Smith   }
901e07b27eSBarry Smith   PetscFunctionReturn(0);
911e07b27eSBarry Smith }
921e07b27eSBarry Smith 
9357f12427SDave May static PetscErrorCode _DMDADetermineGlobalS0(PetscInt dim,PetscMPIInt rank_re,PetscInt Mp_re,PetscInt Np_re,PetscInt Pp_re,
941e07b27eSBarry Smith                                       PetscInt range_i_re[],PetscInt range_j_re[],PetscInt range_k_re[],PetscInt *s0)
951e07b27eSBarry Smith {
96c6a0d831SBarry Smith   PetscInt i,j,k,start_IJK = 0;
971e07b27eSBarry Smith   PetscInt rank_ijk;
981e07b27eSBarry Smith 
991e07b27eSBarry Smith   PetscFunctionBegin;
1001e07b27eSBarry Smith   switch (dim) {
1011e07b27eSBarry Smith   case 1:
1021e07b27eSBarry Smith     for (i=0; i<Mp_re; i++) {
1031e07b27eSBarry Smith       rank_ijk = i;
1041e07b27eSBarry Smith       if (rank_ijk < rank_re) {
1051e07b27eSBarry Smith         start_IJK += range_i_re[i];
1061e07b27eSBarry Smith       }
1071e07b27eSBarry Smith     }
1081e07b27eSBarry Smith     break;
1091e07b27eSBarry Smith     case 2:
1101e07b27eSBarry Smith     for (j=0; j<Np_re; j++) {
1111e07b27eSBarry Smith       for (i=0; i<Mp_re; i++) {
1121e07b27eSBarry Smith         rank_ijk = i + j*Mp_re;
1131e07b27eSBarry Smith         if (rank_ijk < rank_re) {
1141e07b27eSBarry Smith           start_IJK += range_i_re[i]*range_j_re[j];
1151e07b27eSBarry Smith         }
1161e07b27eSBarry Smith       }
1171e07b27eSBarry Smith     }
1181e07b27eSBarry Smith     break;
1191e07b27eSBarry Smith     case 3:
1201e07b27eSBarry Smith     for (k=0; k<Pp_re; k++) {
1211e07b27eSBarry Smith       for (j=0; j<Np_re; j++) {
1221e07b27eSBarry Smith         for (i=0; i<Mp_re; i++) {
1231e07b27eSBarry Smith           rank_ijk = i + j*Mp_re + k*Mp_re*Np_re;
1241e07b27eSBarry Smith           if (rank_ijk < rank_re) {
1251e07b27eSBarry Smith             start_IJK += range_i_re[i]*range_j_re[j]*range_k_re[k];
1261e07b27eSBarry Smith           }
1271e07b27eSBarry Smith         }
1281e07b27eSBarry Smith       }
1291e07b27eSBarry Smith     }
1301e07b27eSBarry Smith     break;
1311e07b27eSBarry Smith   }
1321e07b27eSBarry Smith   *s0 = start_IJK;
1331e07b27eSBarry Smith   PetscFunctionReturn(0);
1341e07b27eSBarry Smith }
1351e07b27eSBarry Smith 
13657f12427SDave May static PetscErrorCode PCTelescopeSetUp_dmda_repart_coors2d(PC_Telescope sred,DM dm,DM subdm)
1371e07b27eSBarry Smith {
1381e07b27eSBarry Smith   DM             cdm;
1391e07b27eSBarry Smith   Vec            coor,coor_natural,perm_coors;
1401e07b27eSBarry Smith   PetscInt       i,j,si,sj,ni,nj,M,N,Ml,Nl,c,nidx;
1411e07b27eSBarry Smith   PetscInt       *fine_indices;
1421e07b27eSBarry Smith   IS             is_fine,is_local;
1431e07b27eSBarry Smith   VecScatter     sctx;
1441e07b27eSBarry Smith 
1451e07b27eSBarry Smith   PetscFunctionBegin;
1465f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinates(dm,&coor));
1471e07b27eSBarry Smith   if (!coor) return(0);
14857f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
1495f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetUniformCoordinates(subdm,0.0,1.0,0.0,1.0,0.0,1.0));
1501e07b27eSBarry Smith   }
1511e07b27eSBarry Smith   /* Get the coordinate vector from the distributed array */
1525f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDM(dm,&cdm));
1535f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDACreateNaturalVector(cdm,&coor_natural));
1541e07b27eSBarry Smith 
1555f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGlobalToNaturalBegin(cdm,coor,INSERT_VALUES,coor_natural));
1565f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGlobalToNaturalEnd(cdm,coor,INSERT_VALUES,coor_natural));
1571e07b27eSBarry Smith 
1581e07b27eSBarry Smith   /* get indices of the guys I want to grab */
1595f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGetInfo(dm,NULL,&M,&N,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL));
16057f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
1615f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDAGetCorners(subdm,&si,&sj,NULL,&ni,&nj,NULL));
16215dd08bcSBarry Smith     Ml = ni;
16315dd08bcSBarry Smith     Nl = nj;
1641e07b27eSBarry Smith   } else {
165c41e779fSDave May     si = sj = 0;
166c41e779fSDave May     ni = nj = 0;
1673ac26c5eSBarry Smith     Ml = Nl = 0;
1681e07b27eSBarry Smith   }
1691e07b27eSBarry Smith 
1705f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(Ml*Nl*2,&fine_indices));
1711e07b27eSBarry Smith   c = 0;
17257f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
1731e07b27eSBarry Smith     for (j=sj; j<sj+nj; j++) {
1741e07b27eSBarry Smith       for (i=si; i<si+ni; i++) {
1751e07b27eSBarry Smith         nidx = (i) + (j)*M;
1761e07b27eSBarry Smith         fine_indices[c  ] = 2 * nidx     ;
1771e07b27eSBarry Smith         fine_indices[c+1] = 2 * nidx + 1 ;
1781e07b27eSBarry Smith         c = c + 2;
1791e07b27eSBarry Smith       }
1801e07b27eSBarry Smith     }
1812c71b3e2SJacob Faibussowitsch     PetscCheckFalse(c != Ml*Nl*2,PETSC_COMM_SELF,PETSC_ERR_PLIB,"c %D should equal 2 * Ml %D * Nl %D",c,Ml,Nl);
1821e07b27eSBarry Smith   }
1831e07b27eSBarry Smith 
1841e07b27eSBarry Smith   /* generate scatter */
1855f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)dm),Ml*Nl*2,fine_indices,PETSC_USE_POINTER,&is_fine));
1865f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateStride(PETSC_COMM_SELF,Ml*Nl*2,0,1,&is_local));
1871e07b27eSBarry Smith 
1881e07b27eSBarry Smith   /* scatter */
1895f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreate(PETSC_COMM_SELF,&perm_coors));
1905f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetSizes(perm_coors,PETSC_DECIDE,Ml*Nl*2));
1915f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetType(perm_coors,VECSEQ));
1921e07b27eSBarry Smith 
1935f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterCreate(coor_natural,is_fine,perm_coors,is_local,&sctx));
1945f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterBegin(sctx,coor_natural,perm_coors,INSERT_VALUES,SCATTER_FORWARD));
1955f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterEnd(  sctx,coor_natural,perm_coors,INSERT_VALUES,SCATTER_FORWARD));
1961e07b27eSBarry Smith   /* access */
19757f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
1981e07b27eSBarry Smith     Vec               _coors;
1991e07b27eSBarry Smith     const PetscScalar *LA_perm;
2001e07b27eSBarry Smith     PetscScalar       *LA_coors;
2011e07b27eSBarry Smith 
2025f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinates(subdm,&_coors));
2035f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArrayRead(perm_coors,&LA_perm));
2045f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(_coors,&LA_coors));
2051e07b27eSBarry Smith     for (i=0; i<Ml*Nl*2; i++) {
2061e07b27eSBarry Smith       LA_coors[i] = LA_perm[i];
2071e07b27eSBarry Smith     }
2085f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(_coors,&LA_coors));
2095f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(perm_coors,&LA_perm));
2101e07b27eSBarry Smith   }
2111e07b27eSBarry Smith 
2121e07b27eSBarry Smith   /* update local coords */
21357f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
2141e07b27eSBarry Smith     DM  _dmc;
2151e07b27eSBarry Smith     Vec _coors,_coors_local;
2165f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinateDM(subdm,&_dmc));
2175f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinates(subdm,&_coors));
2185f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinatesLocal(subdm,&_coors_local));
2195f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGlobalToLocalBegin(_dmc,_coors,INSERT_VALUES,_coors_local));
2205f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGlobalToLocalEnd(_dmc,_coors,INSERT_VALUES,_coors_local));
2211e07b27eSBarry Smith   }
2225f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterDestroy(&sctx));
2235f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&is_fine));
2245f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(fine_indices));
2255f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&is_local));
2265f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&perm_coors));
2275f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&coor_natural));
2281e07b27eSBarry Smith   PetscFunctionReturn(0);
2291e07b27eSBarry Smith }
2301e07b27eSBarry Smith 
23157f12427SDave May static PetscErrorCode PCTelescopeSetUp_dmda_repart_coors3d(PC_Telescope sred,DM dm,DM subdm)
2321e07b27eSBarry Smith {
2331e07b27eSBarry Smith   DM             cdm;
2341e07b27eSBarry Smith   Vec            coor,coor_natural,perm_coors;
2351e07b27eSBarry Smith   PetscInt       i,j,k,si,sj,sk,ni,nj,nk,M,N,P,Ml,Nl,Pl,c,nidx;
2361e07b27eSBarry Smith   PetscInt       *fine_indices;
2371e07b27eSBarry Smith   IS             is_fine,is_local;
2381e07b27eSBarry Smith   VecScatter     sctx;
2391e07b27eSBarry Smith 
2401e07b27eSBarry Smith   PetscFunctionBegin;
2415f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinates(dm,&coor));
2421e07b27eSBarry Smith   if (!coor) PetscFunctionReturn(0);
2431e07b27eSBarry Smith 
24457f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
2455f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetUniformCoordinates(subdm,0.0,1.0,0.0,1.0,0.0,1.0));
2461e07b27eSBarry Smith   }
2471e07b27eSBarry Smith 
2481e07b27eSBarry Smith   /* Get the coordinate vector from the distributed array */
2495f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateDM(dm,&cdm));
2505f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDACreateNaturalVector(cdm,&coor_natural));
2515f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGlobalToNaturalBegin(cdm,coor,INSERT_VALUES,coor_natural));
2525f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGlobalToNaturalEnd(cdm,coor,INSERT_VALUES,coor_natural));
2531e07b27eSBarry Smith 
2541e07b27eSBarry Smith   /* get indices of the guys I want to grab */
2555f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGetInfo(dm,NULL,&M,&N,&P,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL));
2561e07b27eSBarry Smith 
25757f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
2585f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDAGetCorners(subdm,&si,&sj,&sk,&ni,&nj,&nk));
259553d0ae9SBarry Smith     Ml = ni;
260553d0ae9SBarry Smith     Nl = nj;
261553d0ae9SBarry Smith     Pl = nk;
2621e07b27eSBarry Smith   } else {
263c41e779fSDave May     si = sj = sk = 0;
264c41e779fSDave May     ni = nj = nk = 0;
2653ac26c5eSBarry Smith     Ml = Nl = Pl = 0;
2661e07b27eSBarry Smith   }
2671e07b27eSBarry Smith 
2685f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(Ml*Nl*Pl*3,&fine_indices));
2691e07b27eSBarry Smith 
2701e07b27eSBarry Smith   c = 0;
27157f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
2721e07b27eSBarry Smith     for (k=sk; k<sk+nk; k++) {
2731e07b27eSBarry Smith       for (j=sj; j<sj+nj; j++) {
2741e07b27eSBarry Smith         for (i=si; i<si+ni; i++) {
2751e07b27eSBarry Smith           nidx = (i) + (j)*M + (k)*M*N;
2761e07b27eSBarry Smith           fine_indices[c  ] = 3 * nidx     ;
2771e07b27eSBarry Smith           fine_indices[c+1] = 3 * nidx + 1 ;
2781e07b27eSBarry Smith           fine_indices[c+2] = 3 * nidx + 2 ;
2791e07b27eSBarry Smith           c = c + 3;
2801e07b27eSBarry Smith         }
2811e07b27eSBarry Smith       }
2821e07b27eSBarry Smith     }
2831e07b27eSBarry Smith   }
2841e07b27eSBarry Smith 
2851e07b27eSBarry Smith   /* generate scatter */
2865f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)dm),Ml*Nl*Pl*3,fine_indices,PETSC_USE_POINTER,&is_fine));
2875f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateStride(PETSC_COMM_SELF,Ml*Nl*Pl*3,0,1,&is_local));
2881e07b27eSBarry Smith 
2891e07b27eSBarry Smith   /* scatter */
2905f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreate(PETSC_COMM_SELF,&perm_coors));
2915f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetSizes(perm_coors,PETSC_DECIDE,Ml*Nl*Pl*3));
2925f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetType(perm_coors,VECSEQ));
2935f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterCreate(coor_natural,is_fine,perm_coors,is_local,&sctx));
2945f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterBegin(sctx,coor_natural,perm_coors,INSERT_VALUES,SCATTER_FORWARD));
2955f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterEnd(  sctx,coor_natural,perm_coors,INSERT_VALUES,SCATTER_FORWARD));
2961e07b27eSBarry Smith 
2971e07b27eSBarry Smith   /* access */
29857f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
2991e07b27eSBarry Smith     Vec               _coors;
3001e07b27eSBarry Smith     const PetscScalar *LA_perm;
3011e07b27eSBarry Smith     PetscScalar       *LA_coors;
3021e07b27eSBarry Smith 
3035f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinates(subdm,&_coors));
3045f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArrayRead(perm_coors,&LA_perm));
3055f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(_coors,&LA_coors));
3061e07b27eSBarry Smith     for (i=0; i<Ml*Nl*Pl*3; i++) {
3071e07b27eSBarry Smith       LA_coors[i] = LA_perm[i];
3081e07b27eSBarry Smith     }
3095f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(_coors,&LA_coors));
3105f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(perm_coors,&LA_perm));
3111e07b27eSBarry Smith   }
3121e07b27eSBarry Smith 
3131e07b27eSBarry Smith   /* update local coords */
31457f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
3151e07b27eSBarry Smith     DM  _dmc;
3161e07b27eSBarry Smith     Vec _coors,_coors_local;
3171e07b27eSBarry Smith 
3185f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinateDM(subdm,&_dmc));
3195f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinates(subdm,&_coors));
3205f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinatesLocal(subdm,&_coors_local));
3215f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGlobalToLocalBegin(_dmc,_coors,INSERT_VALUES,_coors_local));
3225f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGlobalToLocalEnd(_dmc,_coors,INSERT_VALUES,_coors_local));
3231e07b27eSBarry Smith   }
3241e07b27eSBarry Smith 
3255f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterDestroy(&sctx));
3265f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&is_fine));
3275f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(fine_indices));
3285f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&is_local));
3295f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&perm_coors));
3305f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&coor_natural));
3311e07b27eSBarry Smith   PetscFunctionReturn(0);
3321e07b27eSBarry Smith }
3331e07b27eSBarry Smith 
33457f12427SDave May static PetscErrorCode PCTelescopeSetUp_dmda_repart_coors(PC pc,PC_Telescope sred,PC_Telescope_DMDACtx *ctx)
3351e07b27eSBarry Smith {
3361e07b27eSBarry Smith   PetscInt       dim;
3371e07b27eSBarry Smith   DM             dm,subdm;
3381e07b27eSBarry Smith   PetscSubcomm   psubcomm;
3391e07b27eSBarry Smith   MPI_Comm       comm;
3401e07b27eSBarry Smith   Vec            coor;
3411e07b27eSBarry Smith 
3421e07b27eSBarry Smith   PetscFunctionBegin;
3435f80ce2aSJacob Faibussowitsch   CHKERRQ(PCGetDM(pc,&dm));
3445f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinates(dm,&coor));
3451e07b27eSBarry Smith   if (!coor) PetscFunctionReturn(0);
3461e07b27eSBarry Smith   psubcomm = sred->psubcomm;
3471e07b27eSBarry Smith   comm = PetscSubcommParent(psubcomm);
3481e07b27eSBarry Smith   subdm = ctx->dmrepart;
3491e07b27eSBarry Smith 
3505f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscInfo(pc,"PCTelescope: setting up the coordinates (DMDA)\n"));
3515f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGetInfo(dm,&dim,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL));
3521e07b27eSBarry Smith   switch (dim) {
353b458e8f1SJose E. Roman   case 1:
354b458e8f1SJose E. Roman     SETERRQ(comm,PETSC_ERR_SUP,"Telescope: DMDA (1D) repartitioning not provided");
3555f80ce2aSJacob Faibussowitsch   case 2: CHKERRQ(PCTelescopeSetUp_dmda_repart_coors2d(sred,dm,subdm));
3561e07b27eSBarry Smith     break;
3575f80ce2aSJacob Faibussowitsch   case 3: CHKERRQ(PCTelescopeSetUp_dmda_repart_coors3d(sred,dm,subdm));
3581e07b27eSBarry Smith     break;
3591e07b27eSBarry Smith   }
3601e07b27eSBarry Smith   PetscFunctionReturn(0);
3611e07b27eSBarry Smith }
3621e07b27eSBarry Smith 
3631e07b27eSBarry Smith /* setup repartitioned dm */
3641e07b27eSBarry Smith PetscErrorCode PCTelescopeSetUp_dmda_repart(PC pc,PC_Telescope sred,PC_Telescope_DMDACtx *ctx)
3651e07b27eSBarry Smith {
3661e07b27eSBarry Smith   DM                    dm;
3671e07b27eSBarry Smith   PetscInt              dim,nx,ny,nz,ndof,nsw,sum,k;
3681e07b27eSBarry Smith   DMBoundaryType        bx,by,bz;
3691e07b27eSBarry Smith   DMDAStencilType       stencil;
3701e07b27eSBarry Smith   const PetscInt        *_range_i_re;
3711e07b27eSBarry Smith   const PetscInt        *_range_j_re;
3721e07b27eSBarry Smith   const PetscInt        *_range_k_re;
3731e07b27eSBarry Smith   DMDAInterpolationType itype;
3741e07b27eSBarry Smith   PetscInt              refine_x,refine_y,refine_z;
3751e07b27eSBarry Smith   MPI_Comm              comm,subcomm;
3761e07b27eSBarry Smith   const char            *prefix;
3771e07b27eSBarry Smith 
3781e07b27eSBarry Smith   PetscFunctionBegin;
3791e07b27eSBarry Smith   comm = PetscSubcommParent(sred->psubcomm);
3801e07b27eSBarry Smith   subcomm = PetscSubcommChild(sred->psubcomm);
3815f80ce2aSJacob Faibussowitsch   CHKERRQ(PCGetDM(pc,&dm));
3821e07b27eSBarry Smith 
3835f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGetInfo(dm,&dim,&nx,&ny,&nz,NULL,NULL,NULL,&ndof,&nsw,&bx,&by,&bz,&stencil));
3845f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGetInterpolationType(dm,&itype));
3855f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGetRefinementFactor(dm,&refine_x,&refine_y,&refine_z));
3861e07b27eSBarry Smith 
3871e07b27eSBarry Smith   ctx->dmrepart = NULL;
3881e07b27eSBarry Smith   _range_i_re = _range_j_re = _range_k_re = NULL;
3891e07b27eSBarry Smith   /* Create DMDA on the child communicator */
39057f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
3911e07b27eSBarry Smith     switch (dim) {
3921e07b27eSBarry Smith     case 1:
3935f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscInfo(pc,"PCTelescope: setting up the DMDA on comm subset (1D)\n"));
3945f80ce2aSJacob Faibussowitsch       /*CHKERRQ(DMDACreate1d(subcomm,bx,nx,ndof,nsw,NULL,&ctx->dmrepart));*/
3951e07b27eSBarry Smith       ny = nz = 1;
3961e07b27eSBarry Smith       by = bz = DM_BOUNDARY_NONE;
3971e07b27eSBarry Smith       break;
3981e07b27eSBarry Smith     case 2:
3995f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscInfo(pc,"PCTelescope: setting up the DMDA on comm subset (2D)\n"));
4005f80ce2aSJacob Faibussowitsch       /*CHKERRQ(DMDACreate2d(subcomm,bx,by,stencil,nx,ny, PETSC_DECIDE,PETSC_DECIDE, ndof,nsw, NULL,NULL,&ctx->dmrepart));*/
4011e07b27eSBarry Smith       nz = 1;
4021e07b27eSBarry Smith       bz = DM_BOUNDARY_NONE;
4031e07b27eSBarry Smith       break;
4041e07b27eSBarry Smith     case 3:
4055f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscInfo(pc,"PCTelescope: setting up the DMDA on comm subset (3D)\n"));
4065f80ce2aSJacob Faibussowitsch       /*CHKERRQ(DMDACreate3d(subcomm,bx,by,bz,stencil,nx,ny,nz, PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE, ndof,nsw, NULL,NULL,NULL,&ctx->dmrepart));*/
4071e07b27eSBarry Smith       break;
4081e07b27eSBarry Smith     }
4091e07b27eSBarry Smith     /*
4101e07b27eSBarry Smith      The API DMDACreate1d(), DMDACreate2d(), DMDACreate3d() does not allow us to set/append
4111e07b27eSBarry Smith      a unique option prefix for the DM, thus I prefer to expose the contents of these API's here.
4121e07b27eSBarry Smith      This allows users to control the partitioning of the subDM.
4131e07b27eSBarry Smith     */
4145f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDACreate(subcomm,&ctx->dmrepart));
4151e07b27eSBarry Smith     /* Set unique option prefix name */
4165f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPGetOptionsPrefix(sred->ksp,&prefix));
4175f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetOptionsPrefix(ctx->dmrepart,prefix));
4185f80ce2aSJacob Faibussowitsch     CHKERRQ(DMAppendOptionsPrefix(ctx->dmrepart,"repart_"));
4191e07b27eSBarry Smith     /* standard setup from DMDACreate{1,2,3}d() */
4205f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetDimension(ctx->dmrepart,dim));
4215f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetSizes(ctx->dmrepart,nx,ny,nz));
4225f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetNumProcs(ctx->dmrepart,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE));
4235f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetBoundaryType(ctx->dmrepart,bx,by,bz));
4245f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetDof(ctx->dmrepart,ndof));
4255f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetStencilType(ctx->dmrepart,stencil));
4265f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetStencilWidth(ctx->dmrepart,nsw));
4275f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetOwnershipRanges(ctx->dmrepart,NULL,NULL,NULL));
4285f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetFromOptions(ctx->dmrepart));
4295f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetUp(ctx->dmrepart));
4301e07b27eSBarry Smith     /* Set refinement factors and interpolation type from the partent */
4315f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetRefinementFactor(ctx->dmrepart,refine_x,refine_y,refine_z));
4325f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDASetInterpolationType(ctx->dmrepart,itype));
4331e07b27eSBarry Smith 
4345f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDAGetInfo(ctx->dmrepart,NULL,NULL,NULL,NULL,&ctx->Mp_re,&ctx->Np_re,&ctx->Pp_re,NULL,NULL,NULL,NULL,NULL,NULL));
4355f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDAGetOwnershipRanges(ctx->dmrepart,&_range_i_re,&_range_j_re,&_range_k_re));
4365e897e82SDave May 
4375e897e82SDave May     ctx->dmrepart->ops->creatematrix = dm->ops->creatematrix;
4385e897e82SDave May     ctx->dmrepart->ops->createdomaindecomposition = dm->ops->createdomaindecomposition;
4391e07b27eSBarry Smith   }
4401e07b27eSBarry Smith 
4411e07b27eSBarry Smith   /* generate ranges for repartitioned dm */
4421e07b27eSBarry Smith   /* note - assume rank 0 always participates */
443071fcb05SBarry Smith   /* TODO: use a single MPI call */
4445f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Bcast(&ctx->Mp_re,1,MPIU_INT,0,comm));
4455f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Bcast(&ctx->Np_re,1,MPIU_INT,0,comm));
4465f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Bcast(&ctx->Pp_re,1,MPIU_INT,0,comm));
4471e07b27eSBarry Smith 
4485f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc3(ctx->Mp_re,&ctx->range_i_re,ctx->Np_re,&ctx->range_j_re,ctx->Pp_re,&ctx->range_k_re));
4491e07b27eSBarry Smith 
4505f80ce2aSJacob Faibussowitsch   if (_range_i_re) CHKERRQ(PetscArraycpy(ctx->range_i_re,_range_i_re,ctx->Mp_re));
4515f80ce2aSJacob Faibussowitsch   if (_range_j_re) CHKERRQ(PetscArraycpy(ctx->range_j_re,_range_j_re,ctx->Np_re));
4525f80ce2aSJacob Faibussowitsch   if (_range_k_re) CHKERRQ(PetscArraycpy(ctx->range_k_re,_range_k_re,ctx->Pp_re));
4531e07b27eSBarry Smith 
454071fcb05SBarry Smith   /* TODO: use a single MPI call */
4555f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Bcast(ctx->range_i_re,ctx->Mp_re,MPIU_INT,0,comm));
4565f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Bcast(ctx->range_j_re,ctx->Np_re,MPIU_INT,0,comm));
4575f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Bcast(ctx->range_k_re,ctx->Pp_re,MPIU_INT,0,comm));
4581e07b27eSBarry Smith 
4595f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc3(ctx->Mp_re,&ctx->start_i_re,ctx->Np_re,&ctx->start_j_re,ctx->Pp_re,&ctx->start_k_re));
4601e07b27eSBarry Smith 
4611e07b27eSBarry Smith   sum = 0;
4621e07b27eSBarry Smith   for (k=0; k<ctx->Mp_re; k++) {
4631e07b27eSBarry Smith     ctx->start_i_re[k] = sum;
4641e07b27eSBarry Smith     sum += ctx->range_i_re[k];
4651e07b27eSBarry Smith   }
4661e07b27eSBarry Smith 
4671e07b27eSBarry Smith   sum = 0;
4681e07b27eSBarry Smith   for (k=0; k<ctx->Np_re; k++) {
4691e07b27eSBarry Smith     ctx->start_j_re[k] = sum;
4701e07b27eSBarry Smith     sum += ctx->range_j_re[k];
4711e07b27eSBarry Smith   }
4721e07b27eSBarry Smith 
4731e07b27eSBarry Smith   sum = 0;
4741e07b27eSBarry Smith   for (k=0; k<ctx->Pp_re; k++) {
4751e07b27eSBarry Smith     ctx->start_k_re[k] = sum;
4761e07b27eSBarry Smith     sum += ctx->range_k_re[k];
4771e07b27eSBarry Smith   }
4781e07b27eSBarry Smith 
479ba1c3560SDave May   /* attach repartitioned dm to child ksp */
480ba1c3560SDave May   {
481ba1c3560SDave May     PetscErrorCode (*dmksp_func)(KSP,Mat,Mat,void*);
482ba1c3560SDave May     void           *dmksp_ctx;
483ba1c3560SDave May 
4845f80ce2aSJacob Faibussowitsch     CHKERRQ(DMKSPGetComputeOperators(dm,&dmksp_func,&dmksp_ctx));
485ba1c3560SDave May 
4861e07b27eSBarry Smith     /* attach dm to ksp on sub communicator */
48757f12427SDave May     if (PCTelescope_isActiveRank(sred)) {
4885f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPSetDM(sred->ksp,ctx->dmrepart));
489ba1c3560SDave May 
490c5db1f53SDave May       if (!dmksp_func || sred->ignore_kspcomputeoperators) {
4915f80ce2aSJacob Faibussowitsch         CHKERRQ(KSPSetDMActive(sred->ksp,PETSC_FALSE));
492ba1c3560SDave May       } else {
493ba1c3560SDave May         /* sub ksp inherits dmksp_func and context provided by user */
4945f80ce2aSJacob Faibussowitsch         CHKERRQ(KSPSetComputeOperators(sred->ksp,dmksp_func,dmksp_ctx));
4955f80ce2aSJacob Faibussowitsch         CHKERRQ(KSPSetDMActive(sred->ksp,PETSC_TRUE));
496ba1c3560SDave May       }
497ba1c3560SDave May     }
4981e07b27eSBarry Smith   }
4991e07b27eSBarry Smith   PetscFunctionReturn(0);
5001e07b27eSBarry Smith }
5011e07b27eSBarry Smith 
5021e07b27eSBarry Smith PetscErrorCode PCTelescopeSetUp_dmda_permutation_3d(PC pc,PC_Telescope sred,PC_Telescope_DMDACtx *ctx)
5031e07b27eSBarry Smith {
5041e07b27eSBarry Smith   PetscErrorCode ierr;
5051e07b27eSBarry Smith   DM             dm;
5061e07b27eSBarry Smith   MPI_Comm       comm;
5071e07b27eSBarry Smith   Mat            Pscalar,P;
5081e07b27eSBarry Smith   PetscInt       ndof;
5091e07b27eSBarry Smith   PetscInt       i,j,k,location,startI[3],endI[3],lenI[3],nx,ny,nz;
5101e07b27eSBarry Smith   PetscInt       sr,er,Mr;
5111e07b27eSBarry Smith   Vec            V;
5121e07b27eSBarry Smith 
5131e07b27eSBarry Smith   PetscFunctionBegin;
5145f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscInfo(pc,"PCTelescope: setting up the permutation matrix (DMDA-3D)\n"));
5155f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)pc,&comm));
5161e07b27eSBarry Smith 
5175f80ce2aSJacob Faibussowitsch   CHKERRQ(PCGetDM(pc,&dm));
5185f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGetInfo(dm,NULL,&nx,&ny,&nz,NULL,NULL,NULL,&ndof,NULL,NULL,NULL,NULL,NULL));
5191e07b27eSBarry Smith 
5205f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetGlobalVector(dm,&V));
5215f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetSize(V,&Mr));
5225f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetOwnershipRange(V,&sr,&er));
5235f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreGlobalVector(dm,&V));
5241e07b27eSBarry Smith   sr = sr / ndof;
5251e07b27eSBarry Smith   er = er / ndof;
5261e07b27eSBarry Smith   Mr = Mr / ndof;
5271e07b27eSBarry Smith 
5285f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate(comm,&Pscalar));
5295f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(Pscalar,(er-sr),(er-sr),Mr,Mr));
5305f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetType(Pscalar,MATAIJ));
5315f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJSetPreallocation(Pscalar,1,NULL));
5325f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMPIAIJSetPreallocation(Pscalar,1,NULL,1,NULL));
5331e07b27eSBarry Smith 
5345f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGetCorners(dm,NULL,NULL,NULL,&lenI[0],&lenI[1],&lenI[2]));
5355f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGetCorners(dm,&startI[0],&startI[1],&startI[2],&endI[0],&endI[1],&endI[2]));
5361e07b27eSBarry Smith   endI[0] += startI[0];
5371e07b27eSBarry Smith   endI[1] += startI[1];
5381e07b27eSBarry Smith   endI[2] += startI[2];
5391e07b27eSBarry Smith 
5401e07b27eSBarry Smith   for (k=startI[2]; k<endI[2]; k++) {
5411e07b27eSBarry Smith     for (j=startI[1]; j<endI[1]; j++) {
5421e07b27eSBarry Smith       for (i=startI[0]; i<endI[0]; i++) {
5431e07b27eSBarry Smith         PetscMPIInt rank_ijk_re,rank_reI[3];
5441e07b27eSBarry Smith         PetscInt    s0_re;
545c6a0d831SBarry Smith         PetscInt    ii,jj,kk,local_ijk_re,mapped_ijk;
5461e07b27eSBarry Smith         PetscInt    lenI_re[3];
5471e07b27eSBarry Smith 
5481e07b27eSBarry Smith         location = (i - startI[0]) + (j - startI[1])*lenI[0] + (k - startI[2])*lenI[0]*lenI[1];
5491e07b27eSBarry Smith         ierr = _DMDADetermineRankFromGlobalIJK(3,i,j,k,   ctx->Mp_re,ctx->Np_re,ctx->Pp_re,
5501e07b27eSBarry Smith                                                ctx->start_i_re,ctx->start_j_re,ctx->start_k_re,
5511e07b27eSBarry Smith                                                ctx->range_i_re,ctx->range_j_re,ctx->range_k_re,
5521e07b27eSBarry Smith                                                &rank_reI[0],&rank_reI[1],&rank_reI[2],&rank_ijk_re);CHKERRQ(ierr);
5535f80ce2aSJacob Faibussowitsch         CHKERRQ(_DMDADetermineGlobalS0(3,rank_ijk_re, ctx->Mp_re,ctx->Np_re,ctx->Pp_re, ctx->range_i_re,ctx->range_j_re,ctx->range_k_re, &s0_re));
5541e07b27eSBarry Smith         ii = i - ctx->start_i_re[ rank_reI[0] ];
5552c71b3e2SJacob Faibussowitsch         PetscCheckFalse(ii < 0,PETSC_COMM_SELF,PETSC_ERR_USER,"[dmdarepart-perm3d] index error ii");
5561e07b27eSBarry Smith         jj = j - ctx->start_j_re[ rank_reI[1] ];
5572c71b3e2SJacob Faibussowitsch         PetscCheckFalse(jj < 0,PETSC_COMM_SELF,PETSC_ERR_USER,"[dmdarepart-perm3d] index error jj");
5581e07b27eSBarry Smith         kk = k - ctx->start_k_re[ rank_reI[2] ];
5592c71b3e2SJacob Faibussowitsch         PetscCheckFalse(kk < 0,PETSC_COMM_SELF,PETSC_ERR_USER,"[dmdarepart-perm3d] index error kk");
5601e07b27eSBarry Smith         lenI_re[0] = ctx->range_i_re[ rank_reI[0] ];
5611e07b27eSBarry Smith         lenI_re[1] = ctx->range_j_re[ rank_reI[1] ];
5621e07b27eSBarry Smith         lenI_re[2] = ctx->range_k_re[ rank_reI[2] ];
5631e07b27eSBarry Smith         local_ijk_re = ii + jj * lenI_re[0] + kk * lenI_re[0] * lenI_re[1];
5641e07b27eSBarry Smith         mapped_ijk = s0_re + local_ijk_re;
5655f80ce2aSJacob Faibussowitsch         CHKERRQ(MatSetValue(Pscalar,sr+location,mapped_ijk,1.0,INSERT_VALUES));
5661e07b27eSBarry Smith       }
5671e07b27eSBarry Smith     }
5681e07b27eSBarry Smith   }
5695f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(Pscalar,MAT_FINAL_ASSEMBLY));
5705f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(Pscalar,MAT_FINAL_ASSEMBLY));
5715f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateMAIJ(Pscalar,ndof,&P));
5725f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&Pscalar));
5731e07b27eSBarry Smith   ctx->permutation = P;
5741e07b27eSBarry Smith   PetscFunctionReturn(0);
5751e07b27eSBarry Smith }
5761e07b27eSBarry Smith 
5771e07b27eSBarry Smith PetscErrorCode PCTelescopeSetUp_dmda_permutation_2d(PC pc,PC_Telescope sred,PC_Telescope_DMDACtx *ctx)
5781e07b27eSBarry Smith {
5791e07b27eSBarry Smith   PetscErrorCode ierr;
5801e07b27eSBarry Smith   DM             dm;
5811e07b27eSBarry Smith   MPI_Comm       comm;
5821e07b27eSBarry Smith   Mat            Pscalar,P;
5831e07b27eSBarry Smith   PetscInt       ndof;
5841e07b27eSBarry Smith   PetscInt       i,j,location,startI[2],endI[2],lenI[2],nx,ny,nz;
5851e07b27eSBarry Smith   PetscInt       sr,er,Mr;
5861e07b27eSBarry Smith   Vec            V;
5871e07b27eSBarry Smith 
5881e07b27eSBarry Smith   PetscFunctionBegin;
5895f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscInfo(pc,"PCTelescope: setting up the permutation matrix (DMDA-2D)\n"));
5905f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)pc,&comm));
5915f80ce2aSJacob Faibussowitsch   CHKERRQ(PCGetDM(pc,&dm));
5925f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGetInfo(dm,NULL,&nx,&ny,&nz,NULL,NULL,NULL,&ndof,NULL,NULL,NULL,NULL,NULL));
5935f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetGlobalVector(dm,&V));
5945f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetSize(V,&Mr));
5955f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetOwnershipRange(V,&sr,&er));
5965f80ce2aSJacob Faibussowitsch   CHKERRQ(DMRestoreGlobalVector(dm,&V));
5971e07b27eSBarry Smith   sr = sr / ndof;
5981e07b27eSBarry Smith   er = er / ndof;
5991e07b27eSBarry Smith   Mr = Mr / ndof;
6001e07b27eSBarry Smith 
6015f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate(comm,&Pscalar));
6025f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(Pscalar,(er-sr),(er-sr),Mr,Mr));
6035f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetType(Pscalar,MATAIJ));
6045f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJSetPreallocation(Pscalar,1,NULL));
6055f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMPIAIJSetPreallocation(Pscalar,1,NULL,1,NULL));
6061e07b27eSBarry Smith 
6075f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGetCorners(dm,NULL,NULL,NULL,&lenI[0],&lenI[1],NULL));
6085f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGetCorners(dm,&startI[0],&startI[1],NULL,&endI[0],&endI[1],NULL));
6091e07b27eSBarry Smith   endI[0] += startI[0];
6101e07b27eSBarry Smith   endI[1] += startI[1];
6111e07b27eSBarry Smith 
6121e07b27eSBarry Smith   for (j=startI[1]; j<endI[1]; j++) {
6131e07b27eSBarry Smith     for (i=startI[0]; i<endI[0]; i++) {
6141e07b27eSBarry Smith       PetscMPIInt rank_ijk_re,rank_reI[3];
6151e07b27eSBarry Smith       PetscInt    s0_re;
616c6a0d831SBarry Smith       PetscInt    ii,jj,local_ijk_re,mapped_ijk;
6171e07b27eSBarry Smith       PetscInt    lenI_re[3];
6181e07b27eSBarry Smith 
6191e07b27eSBarry Smith       location = (i - startI[0]) + (j - startI[1])*lenI[0];
6201e07b27eSBarry Smith       ierr = _DMDADetermineRankFromGlobalIJK(2,i,j,0,   ctx->Mp_re,ctx->Np_re,ctx->Pp_re,
6211e07b27eSBarry Smith                                              ctx->start_i_re,ctx->start_j_re,ctx->start_k_re,
6221e07b27eSBarry Smith                                              ctx->range_i_re,ctx->range_j_re,ctx->range_k_re,
6231e07b27eSBarry Smith                                              &rank_reI[0],&rank_reI[1],NULL,&rank_ijk_re);CHKERRQ(ierr);
6241e07b27eSBarry Smith 
6255f80ce2aSJacob Faibussowitsch       CHKERRQ(_DMDADetermineGlobalS0(2,rank_ijk_re, ctx->Mp_re,ctx->Np_re,ctx->Pp_re, ctx->range_i_re,ctx->range_j_re,ctx->range_k_re, &s0_re));
6261e07b27eSBarry Smith 
6271e07b27eSBarry Smith       ii = i - ctx->start_i_re[ rank_reI[0] ];
6282c71b3e2SJacob Faibussowitsch       PetscCheckFalse(ii < 0,PETSC_COMM_SELF,PETSC_ERR_USER,"[dmdarepart-perm2d] index error ii");
6291e07b27eSBarry Smith       jj = j - ctx->start_j_re[ rank_reI[1] ];
6302c71b3e2SJacob Faibussowitsch       PetscCheckFalse(jj < 0,PETSC_COMM_SELF,PETSC_ERR_USER,"[dmdarepart-perm2d] index error jj");
6311e07b27eSBarry Smith 
6321e07b27eSBarry Smith       lenI_re[0] = ctx->range_i_re[ rank_reI[0] ];
6331e07b27eSBarry Smith       lenI_re[1] = ctx->range_j_re[ rank_reI[1] ];
6341e07b27eSBarry Smith       local_ijk_re = ii + jj * lenI_re[0];
6351e07b27eSBarry Smith       mapped_ijk = s0_re + local_ijk_re;
6365f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetValue(Pscalar,sr+location,mapped_ijk,1.0,INSERT_VALUES));
6371e07b27eSBarry Smith     }
6381e07b27eSBarry Smith   }
6395f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(Pscalar,MAT_FINAL_ASSEMBLY));
6405f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(Pscalar,MAT_FINAL_ASSEMBLY));
6415f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateMAIJ(Pscalar,ndof,&P));
6425f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&Pscalar));
6431e07b27eSBarry Smith   ctx->permutation = P;
6441e07b27eSBarry Smith   PetscFunctionReturn(0);
6451e07b27eSBarry Smith }
6461e07b27eSBarry Smith 
6471e07b27eSBarry Smith PetscErrorCode PCTelescopeSetUp_dmda_scatters(PC pc,PC_Telescope sred,PC_Telescope_DMDACtx *ctx)
6481e07b27eSBarry Smith {
6491e07b27eSBarry Smith   Vec            xred,yred,xtmp,x,xp;
6501e07b27eSBarry Smith   VecScatter     scatter;
6511e07b27eSBarry Smith   IS             isin;
6521e07b27eSBarry Smith   Mat            B;
6531e07b27eSBarry Smith   PetscInt       m,bs,st,ed;
6541e07b27eSBarry Smith   MPI_Comm       comm;
6551e07b27eSBarry Smith 
6561e07b27eSBarry Smith   PetscFunctionBegin;
6575f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)pc,&comm));
6585f80ce2aSJacob Faibussowitsch   CHKERRQ(PCGetOperators(pc,NULL,&B));
6595f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateVecs(B,&x,NULL));
6605f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetBlockSize(B,&bs));
6615f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDuplicate(x,&xp));
6623ac26c5eSBarry Smith   m = 0;
6631e07b27eSBarry Smith   xred = NULL;
6641e07b27eSBarry Smith   yred = NULL;
66557f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
6665f80ce2aSJacob Faibussowitsch     CHKERRQ(DMCreateGlobalVector(ctx->dmrepart,&xred));
6675f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDuplicate(xred,&yred));
6685f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetOwnershipRange(xred,&st,&ed));
6695f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateStride(comm,ed-st,st,1,&isin));
6705f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetLocalSize(xred,&m));
6711e07b27eSBarry Smith   } else {
6725f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetOwnershipRange(x,&st,&ed));
6735f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateStride(comm,0,st,1,&isin));
6741e07b27eSBarry Smith   }
6755f80ce2aSJacob Faibussowitsch   CHKERRQ(ISSetBlockSize(isin,bs));
6765f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreate(comm,&xtmp));
6775f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetSizes(xtmp,m,PETSC_DECIDE));
6785f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetBlockSize(xtmp,bs));
6795f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetType(xtmp,((PetscObject)x)->type_name));
6805f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterCreate(x,isin,xtmp,NULL,&scatter));
6811e07b27eSBarry Smith   sred->xred    = xred;
6821e07b27eSBarry Smith   sred->yred    = yred;
6831e07b27eSBarry Smith   sred->isin    = isin;
6841e07b27eSBarry Smith   sred->scatter = scatter;
6851e07b27eSBarry Smith   sred->xtmp    = xtmp;
6861e07b27eSBarry Smith 
6871e07b27eSBarry Smith   ctx->xp       = xp;
6885f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&x));
6891e07b27eSBarry Smith   PetscFunctionReturn(0);
6901e07b27eSBarry Smith }
6911e07b27eSBarry Smith 
6921e07b27eSBarry Smith PetscErrorCode PCTelescopeSetUp_dmda(PC pc,PC_Telescope sred)
6931e07b27eSBarry Smith {
6941e07b27eSBarry Smith   PC_Telescope_DMDACtx *ctx;
6951e07b27eSBarry Smith   PetscInt             dim;
6961e07b27eSBarry Smith   DM                   dm;
6971e07b27eSBarry Smith   MPI_Comm             comm;
6981e07b27eSBarry Smith 
6991e07b27eSBarry Smith   PetscFunctionBegin;
7005f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscInfo(pc,"PCTelescope: setup (DMDA)\n"));
7015f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNew(&ctx));
7021e07b27eSBarry Smith   sred->dm_ctx = (void*)ctx;
7031e07b27eSBarry Smith 
7045f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)pc,&comm));
7055f80ce2aSJacob Faibussowitsch   CHKERRQ(PCGetDM(pc,&dm));
7065f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGetInfo(dm,&dim,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL));
7071e07b27eSBarry Smith 
7081e07b27eSBarry Smith   PCTelescopeSetUp_dmda_repart(pc,sred,ctx);
7091e07b27eSBarry Smith   PCTelescopeSetUp_dmda_repart_coors(pc,sred,ctx);
7101e07b27eSBarry Smith   switch (dim) {
711b458e8f1SJose E. Roman   case 1:
712b458e8f1SJose E. Roman     SETERRQ(comm,PETSC_ERR_SUP,"Telescope: DMDA (1D) repartitioning not provided");
7135f80ce2aSJacob Faibussowitsch   case 2: CHKERRQ(PCTelescopeSetUp_dmda_permutation_2d(pc,sred,ctx));
7141e07b27eSBarry Smith     break;
7155f80ce2aSJacob Faibussowitsch   case 3: CHKERRQ(PCTelescopeSetUp_dmda_permutation_3d(pc,sred,ctx));
7161e07b27eSBarry Smith     break;
7171e07b27eSBarry Smith   }
7185f80ce2aSJacob Faibussowitsch   CHKERRQ(PCTelescopeSetUp_dmda_scatters(pc,sred,ctx));
7191e07b27eSBarry Smith   PetscFunctionReturn(0);
7201e07b27eSBarry Smith }
7211e07b27eSBarry Smith 
722ba1c3560SDave May PetscErrorCode PCTelescopeMatCreate_dmda_dmactivefalse(PC pc,PC_Telescope sred,MatReuse reuse,Mat *A)
7231e07b27eSBarry Smith {
7241e07b27eSBarry Smith   PC_Telescope_DMDACtx *ctx;
7251e07b27eSBarry Smith   MPI_Comm             comm,subcomm;
7261e07b27eSBarry Smith   Mat                  Bperm,Bred,B,P;
7271e07b27eSBarry Smith   PetscInt             nr,nc;
7281e07b27eSBarry Smith   IS                   isrow,iscol;
7291e07b27eSBarry Smith   Mat                  Blocal,*_Blocal;
7301e07b27eSBarry Smith 
7311e07b27eSBarry Smith   PetscFunctionBegin;
7325f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscInfo(pc,"PCTelescope: updating the redundant preconditioned operator (DMDA)\n"));
7335f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)pc,&comm));
7341e07b27eSBarry Smith   subcomm = PetscSubcommChild(sred->psubcomm);
7351e07b27eSBarry Smith   ctx = (PC_Telescope_DMDACtx*)sred->dm_ctx;
7361e07b27eSBarry Smith 
7375f80ce2aSJacob Faibussowitsch   CHKERRQ(PCGetOperators(pc,NULL,&B));
7385f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(B,&nr,&nc));
7391e07b27eSBarry Smith 
7401e07b27eSBarry Smith   P = ctx->permutation;
7415f80ce2aSJacob Faibussowitsch   CHKERRQ(MatPtAP(B,P,MAT_INITIAL_MATRIX,1.1,&Bperm));
7421e07b27eSBarry Smith 
7431e07b27eSBarry Smith   /* Get submatrices */
7441e07b27eSBarry Smith   isrow = sred->isin;
7455f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateStride(comm,nc,0,1,&iscol));
7461e07b27eSBarry Smith 
7475f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateSubMatrices(Bperm,1,&isrow,&iscol,MAT_INITIAL_MATRIX,&_Blocal));
7481e07b27eSBarry Smith   Blocal = *_Blocal;
7491e07b27eSBarry Smith   Bred = NULL;
75057f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
7511e07b27eSBarry Smith     PetscInt mm;
7521e07b27eSBarry Smith 
7531e07b27eSBarry Smith     if (reuse != MAT_INITIAL_MATRIX) {Bred = *A;}
7545f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetSize(Blocal,&mm,NULL));
7555f80ce2aSJacob Faibussowitsch     /* CHKERRQ(MatCreateMPIMatConcatenateSeqMat(subcomm,Blocal,PETSC_DECIDE,reuse,&Bred)); */
7565f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreateMPIMatConcatenateSeqMat(subcomm,Blocal,mm,reuse,&Bred));
7571e07b27eSBarry Smith   }
7581e07b27eSBarry Smith   *A = Bred;
7591e07b27eSBarry Smith 
7605f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&iscol));
7615f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&Bperm));
7625f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroyMatrices(1,&_Blocal));
7631e07b27eSBarry Smith   PetscFunctionReturn(0);
7641e07b27eSBarry Smith }
7651e07b27eSBarry Smith 
766ba1c3560SDave May PetscErrorCode PCTelescopeMatCreate_dmda(PC pc,PC_Telescope sred,MatReuse reuse,Mat *A)
767ba1c3560SDave May {
768ba1c3560SDave May   DM             dm;
769ba1c3560SDave May   PetscErrorCode (*dmksp_func)(KSP,Mat,Mat,void*);
770ba1c3560SDave May   void           *dmksp_ctx;
771ba1c3560SDave May 
772ba1c3560SDave May   PetscFunctionBegin;
7735f80ce2aSJacob Faibussowitsch   CHKERRQ(PCGetDM(pc,&dm));
7745f80ce2aSJacob Faibussowitsch   CHKERRQ(DMKSPGetComputeOperators(dm,&dmksp_func,&dmksp_ctx));
775dc9ee9fdSDave May   /* We assume that dmksp_func = NULL, is equivalent to dmActive = PETSC_FALSE */
7767c5279cbSDave May   if (dmksp_func && !sred->ignore_kspcomputeoperators) {
777ba1c3560SDave May     DM  dmrepart;
77828323a89SDave May     Mat Ak;
779ba1c3560SDave May 
780ba1c3560SDave May     *A = NULL;
78157f12427SDave May     if (PCTelescope_isActiveRank(sred)) {
7825f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPGetDM(sred->ksp,&dmrepart));
783ba1c3560SDave May       if (reuse == MAT_INITIAL_MATRIX) {
7845f80ce2aSJacob Faibussowitsch         CHKERRQ(DMCreateMatrix(dmrepart,&Ak));
785ba1c3560SDave May         *A = Ak;
786ba1c3560SDave May       } else if (reuse == MAT_REUSE_MATRIX) {
787ba1c3560SDave May         Ak = *A;
788ba1c3560SDave May       }
7895c5dbb1cSDave May       /*
7905c5dbb1cSDave May        There is no need to explicitly assemble the operator now,
7915c5dbb1cSDave May        the sub-KSP will call the method provided to KSPSetComputeOperators() during KSPSetUp()
7925c5dbb1cSDave May       */
793ba1c3560SDave May     }
794ba1c3560SDave May   } else {
7955f80ce2aSJacob Faibussowitsch     CHKERRQ(PCTelescopeMatCreate_dmda_dmactivefalse(pc,sred,reuse,A));
796ba1c3560SDave May   }
797ba1c3560SDave May   PetscFunctionReturn(0);
798ba1c3560SDave May }
799ba1c3560SDave May 
800392968a1SPatrick Sanan PetscErrorCode PCTelescopeSubNullSpaceCreate_dmda_Telescope(PC pc,PC_Telescope sred,MatNullSpace nullspace,MatNullSpace *sub_nullspace)
8011e07b27eSBarry Smith {
8021e07b27eSBarry Smith   PetscBool            has_const;
803a947c41eSDave May   PetscInt             i,k,n = 0;
8041e07b27eSBarry Smith   const Vec            *vecs;
805c41e779fSDave May   Vec                  *sub_vecs = NULL;
8061e07b27eSBarry Smith   MPI_Comm             subcomm;
8071e07b27eSBarry Smith   PC_Telescope_DMDACtx *ctx;
8081e07b27eSBarry Smith 
8091e07b27eSBarry Smith   PetscFunctionBegin;
8101e07b27eSBarry Smith   ctx = (PC_Telescope_DMDACtx*)sred->dm_ctx;
8111e07b27eSBarry Smith   subcomm = PetscSubcommChild(sred->psubcomm);
8125f80ce2aSJacob Faibussowitsch   CHKERRQ(MatNullSpaceGetVecs(nullspace,&has_const,&n,&vecs));
8131e07b27eSBarry Smith 
81457f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
8151e07b27eSBarry Smith     /* create new vectors */
816e3acf2f7SBarry Smith     if (n) {
8175f80ce2aSJacob Faibussowitsch       CHKERRQ(VecDuplicateVecs(sred->xred,n,&sub_vecs));
8181e07b27eSBarry Smith     }
8191e07b27eSBarry Smith   }
8201e07b27eSBarry Smith 
8211e07b27eSBarry Smith   /* copy entries */
8221e07b27eSBarry Smith   for (k=0; k<n; k++) {
8231e07b27eSBarry Smith     const PetscScalar *x_array;
8241e07b27eSBarry Smith     PetscScalar       *LA_sub_vec;
82513c30530SDave May     PetscInt          st,ed;
8261e07b27eSBarry Smith 
8271e07b27eSBarry Smith     /* permute vector into ordering associated with re-partitioned dmda */
8285f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMultTranspose(ctx->permutation,vecs[k],ctx->xp));
8291e07b27eSBarry Smith 
8301e07b27eSBarry Smith     /* pull in vector x->xtmp */
8315f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterBegin(sred->scatter,ctx->xp,sred->xtmp,INSERT_VALUES,SCATTER_FORWARD));
8325f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterEnd(sred->scatter,ctx->xp,sred->xtmp,INSERT_VALUES,SCATTER_FORWARD));
8331e07b27eSBarry Smith 
834392968a1SPatrick Sanan     /* copy vector entries into xred */
8355f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArrayRead(sred->xtmp,&x_array));
836ea2b237eSDave May     if (sub_vecs) {
837ea2b237eSDave May       if (sub_vecs[k]) {
8385f80ce2aSJacob Faibussowitsch         CHKERRQ(VecGetOwnershipRange(sub_vecs[k],&st,&ed));
8395f80ce2aSJacob Faibussowitsch         CHKERRQ(VecGetArray(sub_vecs[k],&LA_sub_vec));
8401e07b27eSBarry Smith         for (i=0; i<ed-st; i++) {
8411e07b27eSBarry Smith           LA_sub_vec[i] = x_array[i];
8421e07b27eSBarry Smith         }
8435f80ce2aSJacob Faibussowitsch         CHKERRQ(VecRestoreArray(sub_vecs[k],&LA_sub_vec));
8441e07b27eSBarry Smith       }
845ea2b237eSDave May     }
8465f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(sred->xtmp,&x_array));
8471e07b27eSBarry Smith   }
8481e07b27eSBarry Smith 
84957f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
850d8b9d5b7SPatrick Sanan     /* create new (near) nullspace for redundant object */
8515f80ce2aSJacob Faibussowitsch     CHKERRQ(MatNullSpaceCreate(subcomm,has_const,n,sub_vecs,sub_nullspace));
8525f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDestroyVecs(n,&sub_vecs));
853*28b400f6SJacob Faibussowitsch     PetscCheck(!nullspace->remove,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Propagation of custom remove callbacks not supported when propagating (near) nullspaces with PCTelescope");
854*28b400f6SJacob Faibussowitsch     PetscCheck(!nullspace->rmctx,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Propagation of custom remove callback context not supported when propagating (near) nullspaces with PCTelescope");
855d8b9d5b7SPatrick Sanan   }
856392968a1SPatrick Sanan   PetscFunctionReturn(0);
857392968a1SPatrick Sanan }
858392968a1SPatrick Sanan 
859392968a1SPatrick Sanan PetscErrorCode PCTelescopeMatNullSpaceCreate_dmda(PC pc,PC_Telescope sred,Mat sub_mat)
860392968a1SPatrick Sanan {
861392968a1SPatrick Sanan   Mat            B;
862392968a1SPatrick Sanan 
863392968a1SPatrick Sanan   PetscFunctionBegin;
8645f80ce2aSJacob Faibussowitsch   CHKERRQ(PCGetOperators(pc,NULL,&B));
865392968a1SPatrick Sanan   {
866392968a1SPatrick Sanan     MatNullSpace nullspace,sub_nullspace;
8675f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetNullSpace(B,&nullspace));
868392968a1SPatrick Sanan     if (nullspace) {
8695f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscInfo(pc,"PCTelescope: generating nullspace (DMDA)\n"));
8705f80ce2aSJacob Faibussowitsch       CHKERRQ(PCTelescopeSubNullSpaceCreate_dmda_Telescope(pc,sred,nullspace,&sub_nullspace));
87157f12427SDave May       if (PCTelescope_isActiveRank(sred)) {
8725f80ce2aSJacob Faibussowitsch         CHKERRQ(MatSetNullSpace(sub_mat,sub_nullspace));
8735f80ce2aSJacob Faibussowitsch         CHKERRQ(MatNullSpaceDestroy(&sub_nullspace));
8741e07b27eSBarry Smith       }
875392968a1SPatrick Sanan     }
876392968a1SPatrick Sanan   }
877392968a1SPatrick Sanan   {
878392968a1SPatrick Sanan     MatNullSpace nearnullspace,sub_nearnullspace;
8795f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetNearNullSpace(B,&nearnullspace));
880392968a1SPatrick Sanan     if (nearnullspace) {
8815f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscInfo(pc,"PCTelescope: generating near nullspace (DMDA)\n"));
8825f80ce2aSJacob Faibussowitsch       CHKERRQ(PCTelescopeSubNullSpaceCreate_dmda_Telescope(pc,sred,nearnullspace,&sub_nearnullspace));
88357f12427SDave May       if (PCTelescope_isActiveRank(sred)) {
8845f80ce2aSJacob Faibussowitsch         CHKERRQ(MatSetNearNullSpace(sub_mat,sub_nearnullspace));
8855f80ce2aSJacob Faibussowitsch         CHKERRQ(MatNullSpaceDestroy(&sub_nearnullspace));
886392968a1SPatrick Sanan       }
887392968a1SPatrick Sanan     }
888392968a1SPatrick Sanan   }
8891e07b27eSBarry Smith   PetscFunctionReturn(0);
8901e07b27eSBarry Smith }
8911e07b27eSBarry Smith 
8921e07b27eSBarry Smith PetscErrorCode PCApply_Telescope_dmda(PC pc,Vec x,Vec y)
8931e07b27eSBarry Smith {
8941e07b27eSBarry Smith   PC_Telescope         sred = (PC_Telescope)pc->data;
8951e07b27eSBarry Smith   Mat                  perm;
8961e07b27eSBarry Smith   Vec                  xtmp,xp,xred,yred;
89713c30530SDave May   PetscInt             i,st,ed;
8981e07b27eSBarry Smith   VecScatter           scatter;
8991e07b27eSBarry Smith   PetscScalar          *array;
9001e07b27eSBarry Smith   const PetscScalar    *x_array;
9011e07b27eSBarry Smith   PC_Telescope_DMDACtx *ctx;
9021e07b27eSBarry Smith 
9031e07b27eSBarry Smith   ctx = (PC_Telescope_DMDACtx*)sred->dm_ctx;
9041e07b27eSBarry Smith   xtmp    = sred->xtmp;
9051e07b27eSBarry Smith   scatter = sred->scatter;
9061e07b27eSBarry Smith   xred    = sred->xred;
9071e07b27eSBarry Smith   yred    = sred->yred;
9081e07b27eSBarry Smith   perm    = ctx->permutation;
9091e07b27eSBarry Smith   xp      = ctx->xp;
9101e07b27eSBarry Smith 
9111e07b27eSBarry Smith   PetscFunctionBegin;
9125f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCitationsRegister(citation,&cited));
91314c9fce5SDave May 
9141e07b27eSBarry Smith   /* permute vector into ordering associated with re-partitioned dmda */
9155f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMultTranspose(perm,x,xp));
9161e07b27eSBarry Smith 
9171e07b27eSBarry Smith   /* pull in vector x->xtmp */
9185f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterBegin(scatter,xp,xtmp,INSERT_VALUES,SCATTER_FORWARD));
9195f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterEnd(scatter,xp,xtmp,INSERT_VALUES,SCATTER_FORWARD));
9201e07b27eSBarry Smith 
921a5b23f4aSJose E. Roman   /* copy vector entries into xred */
9225f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(xtmp,&x_array));
9231e07b27eSBarry Smith   if (xred) {
9241e07b27eSBarry Smith     PetscScalar *LA_xred;
9255f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetOwnershipRange(xred,&st,&ed));
9261e07b27eSBarry Smith 
9275f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(xred,&LA_xred));
9281e07b27eSBarry Smith     for (i=0; i<ed-st; i++) {
9291e07b27eSBarry Smith       LA_xred[i] = x_array[i];
9301e07b27eSBarry Smith     }
9315f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(xred,&LA_xred));
9321e07b27eSBarry Smith   }
9335f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(xtmp,&x_array));
9341e07b27eSBarry Smith 
9351e07b27eSBarry Smith   /* solve */
93657f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
9375f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPSolve(sred->ksp,xred,yred));
9385f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPCheckSolve(sred->ksp,pc,yred));
9391e07b27eSBarry Smith   }
9401e07b27eSBarry Smith 
9411e07b27eSBarry Smith   /* return vector */
9425f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(xtmp,&array));
9431e07b27eSBarry Smith   if (yred) {
9441e07b27eSBarry Smith     const PetscScalar *LA_yred;
9455f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetOwnershipRange(yred,&st,&ed));
9465f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArrayRead(yred,&LA_yred));
9471e07b27eSBarry Smith     for (i=0; i<ed-st; i++) {
9481e07b27eSBarry Smith       array[i] = LA_yred[i];
9491e07b27eSBarry Smith     }
9505f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(yred,&LA_yred));
9511e07b27eSBarry Smith   }
9525f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(xtmp,&array));
9535f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterBegin(scatter,xtmp,xp,INSERT_VALUES,SCATTER_REVERSE));
9545f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterEnd(scatter,xtmp,xp,INSERT_VALUES,SCATTER_REVERSE));
9555f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMult(perm,xp,y));
9561e07b27eSBarry Smith   PetscFunctionReturn(0);
9571e07b27eSBarry Smith }
9581e07b27eSBarry Smith 
959f650675bSDave May PetscErrorCode PCApplyRichardson_Telescope_dmda(PC pc,Vec x,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its,PetscBool zeroguess,PetscInt *outits,PCRichardsonConvergedReason *reason)
960f650675bSDave May {
961f650675bSDave May   PC_Telescope         sred = (PC_Telescope)pc->data;
962f650675bSDave May   Mat                  perm;
963a1d91a28SDave May   Vec                  xtmp,xp,yred;
964f650675bSDave May   PetscInt             i,st,ed;
965f650675bSDave May   VecScatter           scatter;
966f650675bSDave May   const PetscScalar    *x_array;
967c41e779fSDave May   PetscBool            default_init_guess_value = PETSC_FALSE;
968f650675bSDave May   PC_Telescope_DMDACtx *ctx;
969f650675bSDave May 
97057f12427SDave May   PetscFunctionBegin;
971f650675bSDave May   ctx = (PC_Telescope_DMDACtx*)sred->dm_ctx;
972f650675bSDave May   xtmp    = sred->xtmp;
973f650675bSDave May   scatter = sred->scatter;
974f650675bSDave May   yred    = sred->yred;
975f650675bSDave May   perm    = ctx->permutation;
976f650675bSDave May   xp      = ctx->xp;
977f650675bSDave May 
9782c71b3e2SJacob Faibussowitsch   PetscCheckFalse(its > 1,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCApplyRichardson_Telescope_dmda only supports max_it = 1");
979f650675bSDave May   *reason = (PCRichardsonConvergedReason)0;
980f650675bSDave May 
981f650675bSDave May   if (!zeroguess) {
9825f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscInfo(pc,"PCTelescopeDMDA: Scattering y for non-zero-initial guess\n"));
983f650675bSDave May     /* permute vector into ordering associated with re-partitioned dmda */
9845f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMultTranspose(perm,y,xp));
985f650675bSDave May 
986f650675bSDave May     /* pull in vector x->xtmp */
9875f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterBegin(scatter,xp,xtmp,INSERT_VALUES,SCATTER_FORWARD));
9885f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterEnd(scatter,xp,xtmp,INSERT_VALUES,SCATTER_FORWARD));
989f650675bSDave May 
990a5b23f4aSJose E. Roman     /* copy vector entries into xred */
9915f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArrayRead(xtmp,&x_array));
992f650675bSDave May     if (yred) {
993f650675bSDave May       PetscScalar *LA_yred;
9945f80ce2aSJacob Faibussowitsch       CHKERRQ(VecGetOwnershipRange(yred,&st,&ed));
9955f80ce2aSJacob Faibussowitsch       CHKERRQ(VecGetArray(yred,&LA_yred));
996f650675bSDave May       for (i=0; i<ed-st; i++) {
997f650675bSDave May         LA_yred[i] = x_array[i];
998f650675bSDave May       }
9995f80ce2aSJacob Faibussowitsch       CHKERRQ(VecRestoreArray(yred,&LA_yred));
1000f650675bSDave May     }
10015f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(xtmp,&x_array));
1002f650675bSDave May   }
1003f650675bSDave May 
100457f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
10055f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPGetInitialGuessNonzero(sred->ksp,&default_init_guess_value));
10065f80ce2aSJacob Faibussowitsch     if (!zeroguess) CHKERRQ(KSPSetInitialGuessNonzero(sred->ksp,PETSC_TRUE));
1007f650675bSDave May   }
1008f650675bSDave May 
10095f80ce2aSJacob Faibussowitsch   CHKERRQ(PCApply_Telescope_dmda(pc,x,y));
1010f650675bSDave May 
101157f12427SDave May   if (PCTelescope_isActiveRank(sred)) {
10125f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPSetInitialGuessNonzero(sred->ksp,default_init_guess_value));
1013f650675bSDave May   }
1014f650675bSDave May 
1015f650675bSDave May   if (!*reason) *reason = PCRICHARDSON_CONVERGED_ITS;
1016f650675bSDave May   *outits = 1;
1017f650675bSDave May   PetscFunctionReturn(0);
1018f650675bSDave May }
1019f650675bSDave May 
10201e07b27eSBarry Smith PetscErrorCode PCReset_Telescope_dmda(PC pc)
10211e07b27eSBarry Smith {
10221e07b27eSBarry Smith   PC_Telescope         sred = (PC_Telescope)pc->data;
10231e07b27eSBarry Smith   PC_Telescope_DMDACtx *ctx;
10241e07b27eSBarry Smith 
10251e07b27eSBarry Smith   PetscFunctionBegin;
10261e07b27eSBarry Smith   ctx = (PC_Telescope_DMDACtx*)sred->dm_ctx;
10275f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&ctx->xp));
10285f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&ctx->permutation));
10295f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDestroy(&ctx->dmrepart));
10305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree3(ctx->range_i_re,ctx->range_j_re,ctx->range_k_re));
10315f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree3(ctx->start_i_re,ctx->start_j_re,ctx->start_k_re));
10321e07b27eSBarry Smith   PetscFunctionReturn(0);
10331e07b27eSBarry Smith }
10341e07b27eSBarry Smith 
10358ef9ca65SPatrick Sanan PetscErrorCode DMView_DA_Short_3d(DM dm,PetscViewer v)
10361e07b27eSBarry Smith {
10371e07b27eSBarry Smith   PetscInt       M,N,P,m,n,p,ndof,nsw;
10381e07b27eSBarry Smith   MPI_Comm       comm;
10391e07b27eSBarry Smith   PetscMPIInt    size;
10401e07b27eSBarry Smith   const char*    prefix;
10411e07b27eSBarry Smith 
10421e07b27eSBarry Smith   PetscFunctionBegin;
10435f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)dm,&comm));
10445f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm,&size));
10455f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetOptionsPrefix(dm,&prefix));
10465f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGetInfo(dm,NULL,&M,&N,&P,&m,&n,&p,&ndof,&nsw,NULL,NULL,NULL,NULL));
10475f80ce2aSJacob Faibussowitsch   if (prefix) CHKERRQ(PetscViewerASCIIPrintf(v,"DMDA Object:    (%s)    %d MPI processes\n",prefix,size));
10485f80ce2aSJacob Faibussowitsch   else CHKERRQ(PetscViewerASCIIPrintf(v,"DMDA Object:    %d MPI processes\n",size));
10495f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerASCIIPrintf(v,"  M %D N %D P %D m %D n %D p %D dof %D overlap %D\n",M,N,P,m,n,p,ndof,nsw));
10501e07b27eSBarry Smith   PetscFunctionReturn(0);
10511e07b27eSBarry Smith }
10521e07b27eSBarry Smith 
10538ef9ca65SPatrick Sanan PetscErrorCode DMView_DA_Short_2d(DM dm,PetscViewer v)
10541e07b27eSBarry Smith {
10551e07b27eSBarry Smith   PetscInt       M,N,m,n,ndof,nsw;
10561e07b27eSBarry Smith   MPI_Comm       comm;
10571e07b27eSBarry Smith   PetscMPIInt    size;
10581e07b27eSBarry Smith   const char*    prefix;
10591e07b27eSBarry Smith 
10601e07b27eSBarry Smith   PetscFunctionBegin;
10615f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)dm,&comm));
10625f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm,&size));
10635f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetOptionsPrefix(dm,&prefix));
10645f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGetInfo(dm,NULL,&M,&N,NULL,&m,&n,NULL,&ndof,&nsw,NULL,NULL,NULL,NULL));
10655f80ce2aSJacob Faibussowitsch   if (prefix) CHKERRQ(PetscViewerASCIIPrintf(v,"DMDA Object:    (%s)    %d MPI processes\n",prefix,size));
10665f80ce2aSJacob Faibussowitsch   else CHKERRQ(PetscViewerASCIIPrintf(v,"DMDA Object:    %d MPI processes\n",size));
10675f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerASCIIPrintf(v,"  M %D N %D m %D n %D dof %D overlap %D\n",M,N,m,n,ndof,nsw));
10681e07b27eSBarry Smith   PetscFunctionReturn(0);
10691e07b27eSBarry Smith }
10701e07b27eSBarry Smith 
10718ef9ca65SPatrick Sanan PetscErrorCode DMView_DA_Short(DM dm,PetscViewer v)
10721e07b27eSBarry Smith {
10731e07b27eSBarry Smith   PetscInt       dim;
10741e07b27eSBarry Smith 
10751e07b27eSBarry Smith   PetscFunctionBegin;
10765f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAGetInfo(dm,&dim,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL));
10771e07b27eSBarry Smith   switch (dim) {
10785f80ce2aSJacob Faibussowitsch   case 2: CHKERRQ(DMView_DA_Short_2d(dm,v));
10791e07b27eSBarry Smith     break;
10805f80ce2aSJacob Faibussowitsch   case 3: CHKERRQ(DMView_DA_Short_3d(dm,v));
10811e07b27eSBarry Smith     break;
10821e07b27eSBarry Smith   }
10831e07b27eSBarry Smith   PetscFunctionReturn(0);
10841e07b27eSBarry Smith }
1085