xref: /petsc/src/ksp/pc/impls/bjacobi/bjacobi.c (revision 28b400f66ebc7ae0049166a2294dfcd3df27e64b)
1dba47a55SKris Buschelman 
24b9ad928SBarry Smith /*
34b9ad928SBarry Smith    Defines a block Jacobi preconditioner.
44b9ad928SBarry Smith */
500e125f8SBarry Smith 
600e125f8SBarry Smith #include <../src/ksp/pc/impls/bjacobi/bjacobi.h> /*I "petscpc.h" I*/
74b9ad928SBarry Smith 
86849ba73SBarry Smith static PetscErrorCode PCSetUp_BJacobi_Singleblock(PC,Mat,Mat);
96849ba73SBarry Smith static PetscErrorCode PCSetUp_BJacobi_Multiblock(PC,Mat,Mat);
105a7e1895SHong Zhang static PetscErrorCode PCSetUp_BJacobi_Multiproc(PC);
114b9ad928SBarry Smith 
126849ba73SBarry Smith static PetscErrorCode PCSetUp_BJacobi(PC pc)
134b9ad928SBarry Smith {
144b9ad928SBarry Smith   PC_BJacobi     *jac = (PC_BJacobi*)pc->data;
154b9ad928SBarry Smith   Mat            mat  = pc->mat,pmat = pc->pmat;
16976e8c5aSLisandro Dalcin   PetscBool      hasop;
1769a612a9SBarry Smith   PetscInt       N,M,start,i,sum,end;
1869a612a9SBarry Smith   PetscInt       bs,i_start=-1,i_end=-1;
1969a612a9SBarry Smith   PetscMPIInt    rank,size;
204b9ad928SBarry Smith 
214b9ad928SBarry Smith   PetscFunctionBegin;
225f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank));
235f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size));
245f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetLocalSize(pc->pmat,&M,&N));
255f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetBlockSize(pc->pmat,&bs));
264b9ad928SBarry Smith 
275a7e1895SHong Zhang   if (jac->n > 0 && jac->n < size) {
285f80ce2aSJacob Faibussowitsch     CHKERRQ(PCSetUp_BJacobi_Multiproc(pc));
295a7e1895SHong Zhang     PetscFunctionReturn(0);
305a7e1895SHong Zhang   }
315a7e1895SHong Zhang 
325a7e1895SHong Zhang   /* --------------------------------------------------------------------------
334b9ad928SBarry Smith       Determines the number of blocks assigned to each processor
345a7e1895SHong Zhang   -----------------------------------------------------------------------------*/
354b9ad928SBarry Smith 
364b9ad928SBarry Smith   /*   local block count  given */
374b9ad928SBarry Smith   if (jac->n_local > 0 && jac->n < 0) {
385f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPIU_Allreduce(&jac->n_local,&jac->n,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc)));
394b9ad928SBarry Smith     if (jac->l_lens) { /* check that user set these correctly */
404b9ad928SBarry Smith       sum = 0;
414b9ad928SBarry Smith       for (i=0; i<jac->n_local; i++) {
422c71b3e2SJacob Faibussowitsch         PetscCheckFalse(jac->l_lens[i]/bs*bs !=jac->l_lens[i],PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat blocksize doesn't match block Jacobi layout");
434b9ad928SBarry Smith         sum += jac->l_lens[i];
444b9ad928SBarry Smith       }
452c71b3e2SJacob Faibussowitsch       PetscCheckFalse(sum != M,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local lens set incorrectly");
464b9ad928SBarry Smith     } else {
475f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(jac->n_local,&jac->l_lens));
482fa5cd67SKarl Rupp       for (i=0; i<jac->n_local; i++) jac->l_lens[i] = bs*((M/bs)/jac->n_local + (((M/bs) % jac->n_local) > i));
494b9ad928SBarry Smith     }
504b9ad928SBarry Smith   } else if (jac->n > 0 && jac->n_local < 0) { /* global block count given */
514b9ad928SBarry Smith     /* global blocks given: determine which ones are local */
524b9ad928SBarry Smith     if (jac->g_lens) {
534b9ad928SBarry Smith       /* check if the g_lens is has valid entries */
544b9ad928SBarry Smith       for (i=0; i<jac->n; i++) {
552c71b3e2SJacob Faibussowitsch         PetscCheckFalse(!jac->g_lens[i],PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Zero block not allowed");
562c71b3e2SJacob Faibussowitsch         PetscCheckFalse(jac->g_lens[i]/bs*bs != jac->g_lens[i],PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat blocksize doesn't match block Jacobi layout");
574b9ad928SBarry Smith       }
584b9ad928SBarry Smith       if (size == 1) {
594b9ad928SBarry Smith         jac->n_local = jac->n;
605f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscMalloc1(jac->n_local,&jac->l_lens));
615f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscArraycpy(jac->l_lens,jac->g_lens,jac->n_local));
624b9ad928SBarry Smith         /* check that user set these correctly */
634b9ad928SBarry Smith         sum = 0;
644b9ad928SBarry Smith         for (i=0; i<jac->n_local; i++) sum += jac->l_lens[i];
652c71b3e2SJacob Faibussowitsch         PetscCheckFalse(sum != M,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Global lens set incorrectly");
664b9ad928SBarry Smith       } else {
675f80ce2aSJacob Faibussowitsch         CHKERRQ(MatGetOwnershipRange(pc->pmat,&start,&end));
684b9ad928SBarry Smith         /* loop over blocks determing first one owned by me */
694b9ad928SBarry Smith         sum = 0;
704b9ad928SBarry Smith         for (i=0; i<jac->n+1; i++) {
714b9ad928SBarry Smith           if (sum == start) { i_start = i; goto start_1;}
724b9ad928SBarry Smith           if (i < jac->n) sum += jac->g_lens[i];
734b9ad928SBarry Smith         }
74e7e72b3dSBarry Smith         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Block sizes used in PCBJacobiSetTotalBlocks()\nare not compatible with parallel matrix layout");
754b9ad928SBarry Smith start_1:
764b9ad928SBarry Smith         for (i=i_start; i<jac->n+1; i++) {
774b9ad928SBarry Smith           if (sum == end) { i_end = i; goto end_1; }
784b9ad928SBarry Smith           if (i < jac->n) sum += jac->g_lens[i];
794b9ad928SBarry Smith         }
80e7e72b3dSBarry Smith         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Block sizes used in PCBJacobiSetTotalBlocks()\nare not compatible with parallel matrix layout");
814b9ad928SBarry Smith end_1:
824b9ad928SBarry Smith         jac->n_local = i_end - i_start;
835f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscMalloc1(jac->n_local,&jac->l_lens));
845f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscArraycpy(jac->l_lens,jac->g_lens+i_start,jac->n_local));
854b9ad928SBarry Smith       }
864b9ad928SBarry Smith     } else { /* no global blocks given, determine then using default layout */
874b9ad928SBarry Smith       jac->n_local = jac->n/size + ((jac->n % size) > rank);
885f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(jac->n_local,&jac->l_lens));
894b9ad928SBarry Smith       for (i=0; i<jac->n_local; i++) {
904b9ad928SBarry Smith         jac->l_lens[i] = ((M/bs)/jac->n_local + (((M/bs) % jac->n_local) > i))*bs;
912c71b3e2SJacob Faibussowitsch         PetscCheckFalse(!jac->l_lens[i],PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Too many blocks given");
924b9ad928SBarry Smith       }
934b9ad928SBarry Smith     }
944b9ad928SBarry Smith   } else if (jac->n < 0 && jac->n_local < 0) { /* no blocks given */
954b9ad928SBarry Smith     jac->n         = size;
964b9ad928SBarry Smith     jac->n_local   = 1;
975f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(1,&jac->l_lens));
984b9ad928SBarry Smith     jac->l_lens[0] = M;
997271b979SBarry Smith   } else { /* jac->n > 0 && jac->n_local > 0 */
1007271b979SBarry Smith     if (!jac->l_lens) {
1015f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(jac->n_local,&jac->l_lens));
1022fa5cd67SKarl Rupp       for (i=0; i<jac->n_local; i++) jac->l_lens[i] = bs*((M/bs)/jac->n_local + (((M/bs) % jac->n_local) > i));
1037271b979SBarry Smith     }
1044b9ad928SBarry Smith   }
1052c71b3e2SJacob Faibussowitsch   PetscCheckFalse(jac->n_local < 1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of blocks is less than number of processors");
1064b9ad928SBarry Smith 
1075a7e1895SHong Zhang   /* -------------------------
1085a7e1895SHong Zhang       Determines mat and pmat
1095a7e1895SHong Zhang   ---------------------------*/
1105f80ce2aSJacob Faibussowitsch   CHKERRQ(MatHasOperation(pc->mat,MATOP_GET_DIAGONAL_BLOCK,&hasop));
111976e8c5aSLisandro Dalcin   if (!hasop && size == 1) {
1124b9ad928SBarry Smith     mat  = pc->mat;
1134b9ad928SBarry Smith     pmat = pc->pmat;
1144b9ad928SBarry Smith   } else {
11549517cdeSBarry Smith     if (pc->useAmat) {
11649517cdeSBarry Smith       /* use block from Amat matrix, not Pmat for local MatMult() */
1175f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetDiagonalBlock(pc->mat,&mat));
1184b9ad928SBarry Smith     }
11949517cdeSBarry Smith     if (pc->pmat != pc->mat || !pc->useAmat) {
1205f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetDiagonalBlock(pc->pmat,&pmat));
1212fa5cd67SKarl Rupp     } else pmat = mat;
1224b9ad928SBarry Smith   }
1234b9ad928SBarry Smith 
1244b9ad928SBarry Smith   /* ------
1254b9ad928SBarry Smith      Setup code depends on the number of blocks
1264b9ad928SBarry Smith   */
127cc1d6079SHong Zhang   if (jac->n_local == 1) {
1285f80ce2aSJacob Faibussowitsch     CHKERRQ(PCSetUp_BJacobi_Singleblock(pc,mat,pmat));
1294b9ad928SBarry Smith   } else {
1305f80ce2aSJacob Faibussowitsch     CHKERRQ(PCSetUp_BJacobi_Multiblock(pc,mat,pmat));
1314b9ad928SBarry Smith   }
1324b9ad928SBarry Smith   PetscFunctionReturn(0);
1334b9ad928SBarry Smith }
1344b9ad928SBarry Smith 
1354b9ad928SBarry Smith /* Default destroy, if it has never been setup */
1366849ba73SBarry Smith static PetscErrorCode PCDestroy_BJacobi(PC pc)
1374b9ad928SBarry Smith {
1384b9ad928SBarry Smith   PC_BJacobi     *jac = (PC_BJacobi*)pc->data;
1394b9ad928SBarry Smith 
1404b9ad928SBarry Smith   PetscFunctionBegin;
1415f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(jac->g_lens));
1425f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(jac->l_lens));
1435f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(pc->data));
1444b9ad928SBarry Smith   PetscFunctionReturn(0);
1454b9ad928SBarry Smith }
1464b9ad928SBarry Smith 
1474416b707SBarry Smith static PetscErrorCode PCSetFromOptions_BJacobi(PetscOptionItems *PetscOptionsObject,PC pc)
1484b9ad928SBarry Smith {
1494b9ad928SBarry Smith   PC_BJacobi     *jac = (PC_BJacobi*)pc->data;
150248bfaf0SJed Brown   PetscInt       blocks,i;
151ace3abfcSBarry Smith   PetscBool      flg;
1524b9ad928SBarry Smith 
1534b9ad928SBarry Smith   PetscFunctionBegin;
1545f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsHead(PetscOptionsObject,"Block Jacobi options"));
1555f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsInt("-pc_bjacobi_blocks","Total number of blocks","PCBJacobiSetTotalBlocks",jac->n,&blocks,&flg));
1565f80ce2aSJacob Faibussowitsch   if (flg) CHKERRQ(PCBJacobiSetTotalBlocks(pc,blocks,NULL));
1575f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsInt("-pc_bjacobi_local_blocks","Local number of blocks","PCBJacobiSetLocalBlocks",jac->n_local,&blocks,&flg));
1585f80ce2aSJacob Faibussowitsch   if (flg) CHKERRQ(PCBJacobiSetLocalBlocks(pc,blocks,NULL));
159248bfaf0SJed Brown   if (jac->ksp) {
160248bfaf0SJed Brown     /* The sub-KSP has already been set up (e.g., PCSetUp_BJacobi_Singleblock), but KSPSetFromOptions was not called
161248bfaf0SJed Brown      * unless we had already been called. */
162248bfaf0SJed Brown     for (i=0; i<jac->n_local; i++) {
1635f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPSetFromOptions(jac->ksp[i]));
164248bfaf0SJed Brown     }
165248bfaf0SJed Brown   }
1665f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsTail());
1674b9ad928SBarry Smith   PetscFunctionReturn(0);
1684b9ad928SBarry Smith }
1694b9ad928SBarry Smith 
1709804daf3SBarry Smith #include <petscdraw.h>
1716849ba73SBarry Smith static PetscErrorCode PCView_BJacobi(PC pc,PetscViewer viewer)
1724b9ad928SBarry Smith {
1734b9ad928SBarry Smith   PC_BJacobi           *jac   = (PC_BJacobi*)pc->data;
174cbe18068SHong Zhang   PC_BJacobi_Multiproc *mpjac = (PC_BJacobi_Multiproc*)jac->data;
1756849ba73SBarry Smith   PetscErrorCode       ierr;
17669a612a9SBarry Smith   PetscMPIInt          rank;
17769a612a9SBarry Smith   PetscInt             i;
178d9884438SBarry Smith   PetscBool            iascii,isstring,isdraw;
1794b9ad928SBarry Smith   PetscViewer          sviewer;
180020d6619SPierre Jolivet   PetscViewerFormat    format;
181020d6619SPierre Jolivet   const char           *prefix;
1824b9ad928SBarry Smith 
1834b9ad928SBarry Smith   PetscFunctionBegin;
1845f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
1855f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring));
1865f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw));
18732077d6dSBarry Smith   if (iascii) {
18849517cdeSBarry Smith     if (pc->useAmat) {
1895f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer,"  using Amat local matrix, number of blocks = %D\n",jac->n));
1904b9ad928SBarry Smith     }
1915f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  number of blocks = %D\n",jac->n));
1925f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank));
1935f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerGetFormat(viewer,&format));
194020d6619SPierre Jolivet     if (format != PETSC_VIEWER_ASCII_INFO_DETAIL) {
1955f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Local solver information for first block is in the following KSP and PC objects on rank 0:\n"));
1965f80ce2aSJacob Faibussowitsch       CHKERRQ(PCGetOptionsPrefix(pc,&prefix));
1975f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Use -%sksp_view ::ascii_info_detail to display information for all blocks\n",prefix?prefix:""));
198933995ecSHong Zhang       if (jac->ksp && !jac->psubcomm) {
1995f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer));
200dd400576SPatrick Sanan         if (rank == 0) {
2015f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIIPushTab(viewer));
2025f80ce2aSJacob Faibussowitsch           CHKERRQ(KSPView(jac->ksp[0],sviewer));
2035f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIIPopTab(viewer));
2044b9ad928SBarry Smith         }
2055f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerFlush(sviewer));
2065f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer));
2075f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerFlush(viewer));
208e4de9e1dSBarry Smith         /*  extra call needed because of the two calls to PetscViewerASCIIPushSynchronized() in PetscViewerGetSubViewer() */
2095f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPopSynchronized(viewer));
210e4fa1014SBarry Smith       } else if (mpjac && jac->ksp && mpjac->psubcomm) {
2115f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerGetSubViewer(viewer,mpjac->psubcomm->child,&sviewer));
212e4fa1014SBarry Smith         if (!mpjac->psubcomm->color) {
2135f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIIPushTab(viewer));
2145f80ce2aSJacob Faibussowitsch           CHKERRQ(KSPView(*(jac->ksp),sviewer));
2155f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIIPopTab(viewer));
216cbe18068SHong Zhang         }
2175f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerFlush(sviewer));
2185f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerRestoreSubViewer(viewer,mpjac->psubcomm->child,&sviewer));
2195f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerFlush(viewer));
2209530cbd7SBarry Smith         /*  extra call needed because of the two calls to PetscViewerASCIIPushSynchronized() in PetscViewerGetSubViewer() */
2215f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPopSynchronized(viewer));
2224b9ad928SBarry Smith       } else {
2235f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerFlush(viewer));
224e4de9e1dSBarry Smith       }
225e4de9e1dSBarry Smith     } else {
2264814766eSBarry Smith       PetscInt n_global;
2275f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPIU_Allreduce(&jac->n_local,&n_global,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc)));
2285f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPushSynchronized(viewer));
2295f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Local solver information for each block is in the following KSP and PC objects:\n"));
23077431f27SBarry Smith       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] number of local blocks = %D, first local block number = %D\n",
2314b9ad928SBarry Smith                                                 rank,jac->n_local,jac->first_local);CHKERRQ(ierr);
2325f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPushTab(viewer));
2335f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer));
234dd2fa690SBarry Smith       for (i=0; i<jac->n_local; i++) {
2355f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer,"[%d] local block number %D\n",rank,i));
2365f80ce2aSJacob Faibussowitsch         CHKERRQ(KSPView(jac->ksp[i],sviewer));
2375f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIISynchronizedPrintf(viewer,"- - - - - - - - - - - - - - - - - -\n"));
2384b9ad928SBarry Smith       }
2395f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer));
2405f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPopTab(viewer));
2415f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerFlush(viewer));
2425f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPopSynchronized(viewer));
2434b9ad928SBarry Smith     }
2444b9ad928SBarry Smith   } else if (isstring) {
2455f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerStringSPrintf(viewer," blks=%D",jac->n));
2465f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer));
2475f80ce2aSJacob Faibussowitsch     if (jac->ksp) CHKERRQ(KSPView(jac->ksp[0],sviewer));
2485f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer));
249d9884438SBarry Smith   } else if (isdraw) {
250d9884438SBarry Smith     PetscDraw draw;
251d9884438SBarry Smith     char      str[25];
252d9884438SBarry Smith     PetscReal x,y,bottom,h;
253d9884438SBarry Smith 
2545f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerDrawGetDraw(viewer,0,&draw));
2555f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscDrawGetCurrentPoint(draw,&x,&y));
2565f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSNPrintf(str,25,"Number blocks %D",jac->n));
2575f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscDrawStringBoxed(draw,x,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h));
258d9884438SBarry Smith     bottom = y - h;
2595f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscDrawPushCurrentPoint(draw,x,bottom));
260d9884438SBarry Smith     /* warning the communicator on viewer is different then on ksp in parallel */
2615f80ce2aSJacob Faibussowitsch     if (jac->ksp) CHKERRQ(KSPView(jac->ksp[0],viewer));
2625f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscDrawPopCurrentPoint(draw));
2634b9ad928SBarry Smith   }
2644b9ad928SBarry Smith   PetscFunctionReturn(0);
2654b9ad928SBarry Smith }
2664b9ad928SBarry Smith 
2674b9ad928SBarry Smith /* -------------------------------------------------------------------------------------*/
2684b9ad928SBarry Smith 
2691e6b0712SBarry Smith static PetscErrorCode  PCBJacobiGetSubKSP_BJacobi(PC pc,PetscInt *n_local,PetscInt *first_local,KSP **ksp)
2704b9ad928SBarry Smith {
271feb237baSPierre Jolivet   PC_BJacobi *jac = (PC_BJacobi*)pc->data;
2724b9ad928SBarry Smith 
2734b9ad928SBarry Smith   PetscFunctionBegin;
274*28b400f6SJacob Faibussowitsch   PetscCheck(pc->setupcalled,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must call KSPSetUp() or PCSetUp() first");
2754b9ad928SBarry Smith 
2764b9ad928SBarry Smith   if (n_local) *n_local = jac->n_local;
2774b9ad928SBarry Smith   if (first_local) *first_local = jac->first_local;
278020d6619SPierre Jolivet   if (ksp) *ksp                 = jac->ksp;
2794b9ad928SBarry Smith   PetscFunctionReturn(0);
2804b9ad928SBarry Smith }
2814b9ad928SBarry Smith 
2821e6b0712SBarry Smith static PetscErrorCode  PCBJacobiSetTotalBlocks_BJacobi(PC pc,PetscInt blocks,PetscInt *lens)
2834b9ad928SBarry Smith {
2844b9ad928SBarry Smith   PC_BJacobi     *jac = (PC_BJacobi*)pc->data;
2854b9ad928SBarry Smith 
2864b9ad928SBarry Smith   PetscFunctionBegin;
2872c71b3e2SJacob Faibussowitsch   PetscCheckFalse(pc->setupcalled > 0 && jac->n!=blocks,PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"Cannot alter number of blocks after PCSetUp()/KSPSetUp() has been called");
2884b9ad928SBarry Smith   jac->n = blocks;
2890a545947SLisandro Dalcin   if (!lens) jac->g_lens = NULL;
2902fa5cd67SKarl Rupp   else {
2915f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(blocks,&jac->g_lens));
2925f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogObjectMemory((PetscObject)pc,blocks*sizeof(PetscInt)));
2935f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(jac->g_lens,lens,blocks));
2944b9ad928SBarry Smith   }
2954b9ad928SBarry Smith   PetscFunctionReturn(0);
2964b9ad928SBarry Smith }
2974b9ad928SBarry Smith 
2981e6b0712SBarry Smith static PetscErrorCode  PCBJacobiGetTotalBlocks_BJacobi(PC pc, PetscInt *blocks, const PetscInt *lens[])
2994b9ad928SBarry Smith {
3004b9ad928SBarry Smith   PC_BJacobi *jac = (PC_BJacobi*) pc->data;
3014b9ad928SBarry Smith 
3024b9ad928SBarry Smith   PetscFunctionBegin;
3034b9ad928SBarry Smith   *blocks = jac->n;
3044b9ad928SBarry Smith   if (lens) *lens = jac->g_lens;
3054b9ad928SBarry Smith   PetscFunctionReturn(0);
3064b9ad928SBarry Smith }
3074b9ad928SBarry Smith 
3081e6b0712SBarry Smith static PetscErrorCode  PCBJacobiSetLocalBlocks_BJacobi(PC pc,PetscInt blocks,const PetscInt lens[])
3094b9ad928SBarry Smith {
3104b9ad928SBarry Smith   PC_BJacobi     *jac;
3114b9ad928SBarry Smith 
3124b9ad928SBarry Smith   PetscFunctionBegin;
3134b9ad928SBarry Smith   jac = (PC_BJacobi*)pc->data;
3144b9ad928SBarry Smith 
3154b9ad928SBarry Smith   jac->n_local = blocks;
3160a545947SLisandro Dalcin   if (!lens) jac->l_lens = NULL;
3172fa5cd67SKarl Rupp   else {
3185f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(blocks,&jac->l_lens));
3195f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogObjectMemory((PetscObject)pc,blocks*sizeof(PetscInt)));
3205f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(jac->l_lens,lens,blocks));
3214b9ad928SBarry Smith   }
3224b9ad928SBarry Smith   PetscFunctionReturn(0);
3234b9ad928SBarry Smith }
3244b9ad928SBarry Smith 
3251e6b0712SBarry Smith static PetscErrorCode  PCBJacobiGetLocalBlocks_BJacobi(PC pc, PetscInt *blocks, const PetscInt *lens[])
3264b9ad928SBarry Smith {
3274b9ad928SBarry Smith   PC_BJacobi *jac = (PC_BJacobi*) pc->data;
3284b9ad928SBarry Smith 
3294b9ad928SBarry Smith   PetscFunctionBegin;
3304b9ad928SBarry Smith   *blocks = jac->n_local;
3314b9ad928SBarry Smith   if (lens) *lens = jac->l_lens;
3324b9ad928SBarry Smith   PetscFunctionReturn(0);
3334b9ad928SBarry Smith }
3344b9ad928SBarry Smith 
3354b9ad928SBarry Smith /* -------------------------------------------------------------------------------------*/
3364b9ad928SBarry Smith 
3374b9ad928SBarry Smith /*@C
3384b9ad928SBarry Smith    PCBJacobiGetSubKSP - Gets the local KSP contexts for all blocks on
3394b9ad928SBarry Smith    this processor.
3404b9ad928SBarry Smith 
3416da92b7fSHong Zhang    Not Collective
3424b9ad928SBarry Smith 
3434b9ad928SBarry Smith    Input Parameter:
3444b9ad928SBarry Smith .  pc - the preconditioner context
3454b9ad928SBarry Smith 
3464b9ad928SBarry Smith    Output Parameters:
3470298fd71SBarry Smith +  n_local - the number of blocks on this processor, or NULL
3480298fd71SBarry Smith .  first_local - the global number of the first block on this processor, or NULL
3494b9ad928SBarry Smith -  ksp - the array of KSP contexts
3504b9ad928SBarry Smith 
3514b9ad928SBarry Smith    Notes:
3524b9ad928SBarry Smith    After PCBJacobiGetSubKSP() the array of KSP contexts is not to be freed.
3534b9ad928SBarry Smith 
3544b9ad928SBarry Smith    Currently for some matrix implementations only 1 block per processor
3554b9ad928SBarry Smith    is supported.
3564b9ad928SBarry Smith 
3574b9ad928SBarry Smith    You must call KSPSetUp() or PCSetUp() before calling PCBJacobiGetSubKSP().
3584b9ad928SBarry Smith 
359196cc216SBarry Smith    Fortran Usage: You must pass in a KSP array that is large enough to contain all the local KSPs.
3602bf68e3eSBarry Smith       You can call PCBJacobiGetSubKSP(pc,nlocal,firstlocal,PETSC_NULL_KSP,ierr) to determine how large the
361196cc216SBarry Smith       KSP array must be.
362196cc216SBarry Smith 
3634b9ad928SBarry Smith    Level: advanced
3644b9ad928SBarry Smith 
365536f90c4SPierre Jolivet .seealso: PCASMGetSubKSP()
3664b9ad928SBarry Smith @*/
3677087cfbeSBarry Smith PetscErrorCode  PCBJacobiGetSubKSP(PC pc,PetscInt *n_local,PetscInt *first_local,KSP *ksp[])
3684b9ad928SBarry Smith {
3694b9ad928SBarry Smith   PetscFunctionBegin;
3700700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
3715f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscUseMethod(pc,"PCBJacobiGetSubKSP_C",(PC,PetscInt*,PetscInt*,KSP **),(pc,n_local,first_local,ksp)));
3724b9ad928SBarry Smith   PetscFunctionReturn(0);
3734b9ad928SBarry Smith }
3744b9ad928SBarry Smith 
3754b9ad928SBarry Smith /*@
3764b9ad928SBarry Smith    PCBJacobiSetTotalBlocks - Sets the global number of blocks for the block
3774b9ad928SBarry Smith    Jacobi preconditioner.
3784b9ad928SBarry Smith 
3794b9ad928SBarry Smith    Collective on PC
3804b9ad928SBarry Smith 
3814b9ad928SBarry Smith    Input Parameters:
3824b9ad928SBarry Smith +  pc - the preconditioner context
3834b9ad928SBarry Smith .  blocks - the number of blocks
3844b9ad928SBarry Smith -  lens - [optional] integer array containing the size of each block
3854b9ad928SBarry Smith 
3864b9ad928SBarry Smith    Options Database Key:
3874b9ad928SBarry Smith .  -pc_bjacobi_blocks <blocks> - Sets the number of global blocks
3884b9ad928SBarry Smith 
3894b9ad928SBarry Smith    Notes:
3904b9ad928SBarry Smith    Currently only a limited number of blocking configurations are supported.
3914b9ad928SBarry Smith    All processors sharing the PC must call this routine with the same data.
3924b9ad928SBarry Smith 
3934b9ad928SBarry Smith    Level: intermediate
3944b9ad928SBarry Smith 
39549517cdeSBarry Smith .seealso: PCSetUseAmat(), PCBJacobiSetLocalBlocks()
3964b9ad928SBarry Smith @*/
3977087cfbeSBarry Smith PetscErrorCode  PCBJacobiSetTotalBlocks(PC pc,PetscInt blocks,const PetscInt lens[])
3984b9ad928SBarry Smith {
3994b9ad928SBarry Smith   PetscFunctionBegin;
4000700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
4012c71b3e2SJacob Faibussowitsch   PetscCheckFalse(blocks <= 0,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Must have positive blocks");
4025f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(pc,"PCBJacobiSetTotalBlocks_C",(PC,PetscInt,const PetscInt[]),(pc,blocks,lens)));
4034b9ad928SBarry Smith   PetscFunctionReturn(0);
4044b9ad928SBarry Smith }
4054b9ad928SBarry Smith 
4064b9ad928SBarry Smith /*@C
4074b9ad928SBarry Smith    PCBJacobiGetTotalBlocks - Gets the global number of blocks for the block
4084b9ad928SBarry Smith    Jacobi preconditioner.
4094b9ad928SBarry Smith 
410ad4df100SBarry Smith    Not Collective
4114b9ad928SBarry Smith 
4124b9ad928SBarry Smith    Input Parameter:
4134b9ad928SBarry Smith .  pc - the preconditioner context
4144b9ad928SBarry Smith 
4154b9ad928SBarry Smith    Output parameters:
4164b9ad928SBarry Smith +  blocks - the number of blocks
4174b9ad928SBarry Smith -  lens - integer array containing the size of each block
4184b9ad928SBarry Smith 
4194b9ad928SBarry Smith    Level: intermediate
4204b9ad928SBarry Smith 
42149517cdeSBarry Smith .seealso: PCSetUseAmat(), PCBJacobiGetLocalBlocks()
4224b9ad928SBarry Smith @*/
4237087cfbeSBarry Smith PetscErrorCode  PCBJacobiGetTotalBlocks(PC pc, PetscInt *blocks, const PetscInt *lens[])
4244b9ad928SBarry Smith {
4254b9ad928SBarry Smith   PetscFunctionBegin;
4260700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID,1);
4274482741eSBarry Smith   PetscValidIntPointer(blocks,2);
4285f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscUseMethod(pc,"PCBJacobiGetTotalBlocks_C",(PC,PetscInt*, const PetscInt *[]),(pc,blocks,lens)));
4294b9ad928SBarry Smith   PetscFunctionReturn(0);
4304b9ad928SBarry Smith }
4314b9ad928SBarry Smith 
4324b9ad928SBarry Smith /*@
4334b9ad928SBarry Smith    PCBJacobiSetLocalBlocks - Sets the local number of blocks for the block
4344b9ad928SBarry Smith    Jacobi preconditioner.
4354b9ad928SBarry Smith 
4364b9ad928SBarry Smith    Not Collective
4374b9ad928SBarry Smith 
4384b9ad928SBarry Smith    Input Parameters:
4394b9ad928SBarry Smith +  pc - the preconditioner context
4404b9ad928SBarry Smith .  blocks - the number of blocks
4414b9ad928SBarry Smith -  lens - [optional] integer array containing size of each block
4424b9ad928SBarry Smith 
443342c94f9SMatthew G. Knepley    Options Database Key:
444342c94f9SMatthew G. Knepley .  -pc_bjacobi_local_blocks <blocks> - Sets the number of local blocks
445342c94f9SMatthew G. Knepley 
4464b9ad928SBarry Smith    Note:
4474b9ad928SBarry Smith    Currently only a limited number of blocking configurations are supported.
4484b9ad928SBarry Smith 
4494b9ad928SBarry Smith    Level: intermediate
4504b9ad928SBarry Smith 
45149517cdeSBarry Smith .seealso: PCSetUseAmat(), PCBJacobiSetTotalBlocks()
4524b9ad928SBarry Smith @*/
4537087cfbeSBarry Smith PetscErrorCode  PCBJacobiSetLocalBlocks(PC pc,PetscInt blocks,const PetscInt lens[])
4544b9ad928SBarry Smith {
4554b9ad928SBarry Smith   PetscFunctionBegin;
4560700a824SBarry Smith   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
4572c71b3e2SJacob Faibussowitsch   PetscCheckFalse(blocks < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must have nonegative blocks");
4585f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(pc,"PCBJacobiSetLocalBlocks_C",(PC,PetscInt,const PetscInt []),(pc,blocks,lens)));
4594b9ad928SBarry Smith   PetscFunctionReturn(0);
4604b9ad928SBarry Smith }
4614b9ad928SBarry Smith 
4624b9ad928SBarry Smith /*@C
4634b9ad928SBarry Smith    PCBJacobiGetLocalBlocks - Gets the local number of blocks for the block
4644b9ad928SBarry Smith    Jacobi preconditioner.
4654b9ad928SBarry Smith 
4664b9ad928SBarry Smith    Not Collective
4674b9ad928SBarry Smith 
4684b9ad928SBarry Smith    Input Parameters:
4694b9ad928SBarry Smith +  pc - the preconditioner context
4704b9ad928SBarry Smith .  blocks - the number of blocks
4714b9ad928SBarry Smith -  lens - [optional] integer array containing size of each block
4724b9ad928SBarry Smith 
4734b9ad928SBarry Smith    Note:
4744b9ad928SBarry Smith    Currently only a limited number of blocking configurations are supported.
4754b9ad928SBarry Smith 
4764b9ad928SBarry Smith    Level: intermediate
4774b9ad928SBarry Smith 
47849517cdeSBarry Smith .seealso: PCSetUseAmat(), PCBJacobiGetTotalBlocks()
4794b9ad928SBarry Smith @*/
4807087cfbeSBarry Smith PetscErrorCode  PCBJacobiGetLocalBlocks(PC pc, PetscInt *blocks, const PetscInt *lens[])
4814b9ad928SBarry Smith {
4824b9ad928SBarry Smith   PetscFunctionBegin;
4830700a824SBarry Smith   PetscValidHeaderSpecific(pc, PC_CLASSID,1);
4844482741eSBarry Smith   PetscValidIntPointer(blocks,2);
4855f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscUseMethod(pc,"PCBJacobiGetLocalBlocks_C",(PC,PetscInt*, const PetscInt *[]),(pc,blocks,lens)));
4864b9ad928SBarry Smith   PetscFunctionReturn(0);
4874b9ad928SBarry Smith }
4884b9ad928SBarry Smith 
4894b9ad928SBarry Smith /* -----------------------------------------------------------------------------------*/
4904b9ad928SBarry Smith 
4914b9ad928SBarry Smith /*MC
4924b9ad928SBarry Smith    PCBJACOBI - Use block Jacobi preconditioning, each block is (approximately) solved with
4934b9ad928SBarry Smith            its own KSP object.
4944b9ad928SBarry Smith 
4954b9ad928SBarry Smith    Options Database Keys:
496011ea8aeSBarry Smith +  -pc_use_amat - use Amat to apply block of operator in inner Krylov method
497011ea8aeSBarry Smith -  -pc_bjacobi_blocks <n> - use n total blocks
4984b9ad928SBarry Smith 
49995452b02SPatrick Sanan    Notes:
50095452b02SPatrick Sanan      Each processor can have one or more blocks, or a single block can be shared by several processes. Defaults to one block per processor.
5014b9ad928SBarry Smith 
5024b9ad928SBarry Smith      To set options on the solvers for each block append -sub_ to all the KSP, KSP, and PC
503d7ee0231SBarry Smith         options database keys. For example, -sub_pc_type ilu -sub_pc_factor_levels 1 -sub_ksp_type preonly
5044b9ad928SBarry Smith 
505a8c7a070SBarry Smith      To set the options on the solvers separate for each block call PCBJacobiGetSubKSP()
5064b9ad928SBarry Smith          and set the options directly on the resulting KSP object (you can access its PC
5074b9ad928SBarry Smith          KSPGetPC())
5084b9ad928SBarry Smith 
509e9e886b6SKarl Rupp      For GPU-based vectors (CUDA, ViennaCL) it is recommended to use exactly one block per MPI process for best
5102210c163SDominic Meiser          performance.  Different block partitioning may lead to additional data transfers
5112210c163SDominic Meiser          between host and GPU that lead to degraded performance.
5122210c163SDominic Meiser 
513011ea8aeSBarry Smith      The options prefix for each block is sub_, for example -sub_pc_type lu.
514011ea8aeSBarry Smith 
515011ea8aeSBarry Smith      When multiple processes share a single block, each block encompasses exactly all the unknowns owned its set of processes.
516011ea8aeSBarry Smith 
51790dfcc32SBarry Smith      See PCJACOBI for point Jacobi preconditioning, PCVPBJACOBI for variable size point block Jacobi and PCPBJACOBI for large blocks
51890dfcc32SBarry Smith 
5194b9ad928SBarry Smith    Level: beginner
5204b9ad928SBarry Smith 
5214b9ad928SBarry Smith .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
52249517cdeSBarry Smith            PCASM, PCSetUseAmat(), PCGetUseAmat(), PCBJacobiGetSubKSP(), PCBJacobiSetTotalBlocks(),
52390dfcc32SBarry Smith            PCBJacobiSetLocalBlocks(), PCSetModifySubMatrices(), PCJACOBI, PCVPBJACOBI, PCPBJACOBI
5244b9ad928SBarry Smith M*/
5254b9ad928SBarry Smith 
5268cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_BJacobi(PC pc)
5274b9ad928SBarry Smith {
52869a612a9SBarry Smith   PetscMPIInt    rank;
5294b9ad928SBarry Smith   PC_BJacobi     *jac;
5304b9ad928SBarry Smith 
5314b9ad928SBarry Smith   PetscFunctionBegin;
5325f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNewLog(pc,&jac));
5335f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank));
5342fa5cd67SKarl Rupp 
5350a545947SLisandro Dalcin   pc->ops->apply           = NULL;
5367b6e2003SPierre Jolivet   pc->ops->matapply        = NULL;
5370a545947SLisandro Dalcin   pc->ops->applytranspose  = NULL;
5384b9ad928SBarry Smith   pc->ops->setup           = PCSetUp_BJacobi;
5394b9ad928SBarry Smith   pc->ops->destroy         = PCDestroy_BJacobi;
5404b9ad928SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_BJacobi;
5414b9ad928SBarry Smith   pc->ops->view            = PCView_BJacobi;
5420a545947SLisandro Dalcin   pc->ops->applyrichardson = NULL;
5434b9ad928SBarry Smith 
5444b9ad928SBarry Smith   pc->data               = (void*)jac;
5454b9ad928SBarry Smith   jac->n                 = -1;
5464b9ad928SBarry Smith   jac->n_local           = -1;
5474b9ad928SBarry Smith   jac->first_local       = rank;
5480a545947SLisandro Dalcin   jac->ksp               = NULL;
5490a545947SLisandro Dalcin   jac->g_lens            = NULL;
5500a545947SLisandro Dalcin   jac->l_lens            = NULL;
5510a545947SLisandro Dalcin   jac->psubcomm          = NULL;
5524b9ad928SBarry Smith 
5535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBJacobiGetSubKSP_C",PCBJacobiGetSubKSP_BJacobi));
5545f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBJacobiSetTotalBlocks_C",PCBJacobiSetTotalBlocks_BJacobi));
5555f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBJacobiGetTotalBlocks_C",PCBJacobiGetTotalBlocks_BJacobi));
5565f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBJacobiSetLocalBlocks_C",PCBJacobiSetLocalBlocks_BJacobi));
5575f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBJacobiGetLocalBlocks_C",PCBJacobiGetLocalBlocks_BJacobi));
5584b9ad928SBarry Smith   PetscFunctionReturn(0);
5594b9ad928SBarry Smith }
5604b9ad928SBarry Smith 
5614b9ad928SBarry Smith /* --------------------------------------------------------------------------------------------*/
5624b9ad928SBarry Smith /*
5634b9ad928SBarry Smith         These are for a single block per processor; works for AIJ, BAIJ; Seq and MPI
5644b9ad928SBarry Smith */
56581f0254dSBarry Smith static PetscErrorCode PCReset_BJacobi_Singleblock(PC pc)
5664b9ad928SBarry Smith {
5674b9ad928SBarry Smith   PC_BJacobi             *jac  = (PC_BJacobi*)pc->data;
5684b9ad928SBarry Smith   PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data;
5694b9ad928SBarry Smith 
5704b9ad928SBarry Smith   PetscFunctionBegin;
5715f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPReset(jac->ksp[0]));
5725f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&bjac->x));
5735f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&bjac->y));
574e91c6855SBarry Smith   PetscFunctionReturn(0);
575e91c6855SBarry Smith }
576e91c6855SBarry Smith 
57781f0254dSBarry Smith static PetscErrorCode PCDestroy_BJacobi_Singleblock(PC pc)
578e91c6855SBarry Smith {
579e91c6855SBarry Smith   PC_BJacobi             *jac  = (PC_BJacobi*)pc->data;
580e91c6855SBarry Smith   PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data;
581e91c6855SBarry Smith 
582e91c6855SBarry Smith   PetscFunctionBegin;
5835f80ce2aSJacob Faibussowitsch   CHKERRQ(PCReset_BJacobi_Singleblock(pc));
5845f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPDestroy(&jac->ksp[0]));
5855f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(jac->ksp));
5865f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(jac->l_lens));
5875f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(jac->g_lens));
5885f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(bjac));
5895f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(pc->data));
5904b9ad928SBarry Smith   PetscFunctionReturn(0);
5914b9ad928SBarry Smith }
5924b9ad928SBarry Smith 
59381f0254dSBarry Smith static PetscErrorCode PCSetUpOnBlocks_BJacobi_Singleblock(PC pc)
5944b9ad928SBarry Smith {
5954b9ad928SBarry Smith   PC_BJacobi         *jac = (PC_BJacobi*)pc->data;
5962295b7c8SHong Zhang   KSP                subksp = jac->ksp[0];
597539c167fSBarry Smith   KSPConvergedReason reason;
5984b9ad928SBarry Smith 
5994b9ad928SBarry Smith   PetscFunctionBegin;
6005f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPSetUp(subksp));
6015f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPGetConvergedReason(subksp,&reason));
602c0decd05SBarry Smith   if (reason == KSP_DIVERGED_PC_FAILED) {
603261222b2SHong Zhang     pc->failedreason = PC_SUBPC_ERROR;
6042295b7c8SHong Zhang   }
6054b9ad928SBarry Smith   PetscFunctionReturn(0);
6064b9ad928SBarry Smith }
6074b9ad928SBarry Smith 
60881f0254dSBarry Smith static PetscErrorCode PCApply_BJacobi_Singleblock(PC pc,Vec x,Vec y)
6094b9ad928SBarry Smith {
6104b9ad928SBarry Smith   PC_BJacobi             *jac  = (PC_BJacobi*)pc->data;
6114b9ad928SBarry Smith   PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data;
6126e111a19SKarl Rupp 
6134b9ad928SBarry Smith   PetscFunctionBegin;
6145f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetLocalVectorRead(x, bjac->x));
6155f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetLocalVector(y, bjac->y));
616bba28a21SBarry Smith   /* Since the inner KSP matrix may point directly to the diagonal block of an MPI matrix the inner
617910cf402Sprj-      matrix may change even if the outer KSP/PC has not updated the preconditioner, this will trigger a rebuild
618910cf402Sprj-      of the inner preconditioner automatically unless we pass down the outer preconditioners reuse flag.*/
6195f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPSetReusePreconditioner(jac->ksp[0],pc->reusepreconditioner));
6205f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPSolve(jac->ksp[0],bjac->x,bjac->y));
6215f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPCheckSolve(jac->ksp[0],pc,bjac->y));
6225f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreLocalVectorRead(x, bjac->x));
6235f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreLocalVector(y, bjac->y));
6244b9ad928SBarry Smith   PetscFunctionReturn(0);
6254b9ad928SBarry Smith }
6264b9ad928SBarry Smith 
6277b6e2003SPierre Jolivet static PetscErrorCode PCMatApply_BJacobi_Singleblock(PC pc,Mat X,Mat Y)
6287b6e2003SPierre Jolivet {
6297b6e2003SPierre Jolivet   PC_BJacobi     *jac  = (PC_BJacobi*)pc->data;
6307b6e2003SPierre Jolivet   Mat            sX,sY;
6317b6e2003SPierre Jolivet 
6327b6e2003SPierre Jolivet   PetscFunctionBegin;
6337b6e2003SPierre Jolivet   /* Since the inner KSP matrix may point directly to the diagonal block of an MPI matrix the inner
6347b6e2003SPierre Jolivet      matrix may change even if the outer KSP/PC has not updated the preconditioner, this will trigger a rebuild
6357b6e2003SPierre Jolivet      of the inner preconditioner automatically unless we pass down the outer preconditioners reuse flag.*/
6365f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPSetReusePreconditioner(jac->ksp[0],pc->reusepreconditioner));
6375f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDenseGetLocalMatrix(X,&sX));
6385f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDenseGetLocalMatrix(Y,&sY));
6395f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPMatSolve(jac->ksp[0],sX,sY));
6407b6e2003SPierre Jolivet   PetscFunctionReturn(0);
6417b6e2003SPierre Jolivet }
6427b6e2003SPierre Jolivet 
64381f0254dSBarry Smith static PetscErrorCode PCApplySymmetricLeft_BJacobi_Singleblock(PC pc,Vec x,Vec y)
6444b9ad928SBarry Smith {
6454b9ad928SBarry Smith   PC_BJacobi             *jac  = (PC_BJacobi*)pc->data;
6464b9ad928SBarry Smith   PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data;
647d9ca1df4SBarry Smith   PetscScalar            *y_array;
648d9ca1df4SBarry Smith   const PetscScalar      *x_array;
6494b9ad928SBarry Smith   PC                     subpc;
6504b9ad928SBarry Smith 
6514b9ad928SBarry Smith   PetscFunctionBegin;
6524b9ad928SBarry Smith   /*
6534b9ad928SBarry Smith       The VecPlaceArray() is to avoid having to copy the
6544b9ad928SBarry Smith     y vector into the bjac->x vector. The reason for
6554b9ad928SBarry Smith     the bjac->x vector is that we need a sequential vector
6564b9ad928SBarry Smith     for the sequential solve.
6574b9ad928SBarry Smith   */
6585f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(x,&x_array));
6595f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(y,&y_array));
6605f80ce2aSJacob Faibussowitsch   CHKERRQ(VecPlaceArray(bjac->x,x_array));
6615f80ce2aSJacob Faibussowitsch   CHKERRQ(VecPlaceArray(bjac->y,y_array));
6624b9ad928SBarry Smith   /* apply the symmetric left portion of the inner PC operator */
6634b9ad928SBarry Smith   /* note this by-passes the inner KSP and its options completely */
6645f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPGetPC(jac->ksp[0],&subpc));
6655f80ce2aSJacob Faibussowitsch   CHKERRQ(PCApplySymmetricLeft(subpc,bjac->x,bjac->y));
6665f80ce2aSJacob Faibussowitsch   CHKERRQ(VecResetArray(bjac->x));
6675f80ce2aSJacob Faibussowitsch   CHKERRQ(VecResetArray(bjac->y));
6685f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(x,&x_array));
6695f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(y,&y_array));
6704b9ad928SBarry Smith   PetscFunctionReturn(0);
6714b9ad928SBarry Smith }
6724b9ad928SBarry Smith 
67381f0254dSBarry Smith static PetscErrorCode PCApplySymmetricRight_BJacobi_Singleblock(PC pc,Vec x,Vec y)
6744b9ad928SBarry Smith {
6754b9ad928SBarry Smith   PC_BJacobi             *jac  = (PC_BJacobi*)pc->data;
6764b9ad928SBarry Smith   PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data;
677d9ca1df4SBarry Smith   PetscScalar            *y_array;
678d9ca1df4SBarry Smith   const PetscScalar      *x_array;
6794b9ad928SBarry Smith   PC                     subpc;
6804b9ad928SBarry Smith 
6814b9ad928SBarry Smith   PetscFunctionBegin;
6824b9ad928SBarry Smith   /*
6834b9ad928SBarry Smith       The VecPlaceArray() is to avoid having to copy the
6844b9ad928SBarry Smith     y vector into the bjac->x vector. The reason for
6854b9ad928SBarry Smith     the bjac->x vector is that we need a sequential vector
6864b9ad928SBarry Smith     for the sequential solve.
6874b9ad928SBarry Smith   */
6885f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(x,&x_array));
6895f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(y,&y_array));
6905f80ce2aSJacob Faibussowitsch   CHKERRQ(VecPlaceArray(bjac->x,x_array));
6915f80ce2aSJacob Faibussowitsch   CHKERRQ(VecPlaceArray(bjac->y,y_array));
6924b9ad928SBarry Smith 
6934b9ad928SBarry Smith   /* apply the symmetric right portion of the inner PC operator */
6944b9ad928SBarry Smith   /* note this by-passes the inner KSP and its options completely */
6954b9ad928SBarry Smith 
6965f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPGetPC(jac->ksp[0],&subpc));
6975f80ce2aSJacob Faibussowitsch   CHKERRQ(PCApplySymmetricRight(subpc,bjac->x,bjac->y));
6984b9ad928SBarry Smith 
6995f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(x,&x_array));
7005f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(y,&y_array));
7014b9ad928SBarry Smith   PetscFunctionReturn(0);
7024b9ad928SBarry Smith }
7034b9ad928SBarry Smith 
70481f0254dSBarry Smith static PetscErrorCode PCApplyTranspose_BJacobi_Singleblock(PC pc,Vec x,Vec y)
7054b9ad928SBarry Smith {
7064b9ad928SBarry Smith   PC_BJacobi             *jac  = (PC_BJacobi*)pc->data;
7074b9ad928SBarry Smith   PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data;
708d9ca1df4SBarry Smith   PetscScalar            *y_array;
709d9ca1df4SBarry Smith   const PetscScalar      *x_array;
7104b9ad928SBarry Smith 
7114b9ad928SBarry Smith   PetscFunctionBegin;
7124b9ad928SBarry Smith   /*
7134b9ad928SBarry Smith       The VecPlaceArray() is to avoid having to copy the
7144b9ad928SBarry Smith     y vector into the bjac->x vector. The reason for
7154b9ad928SBarry Smith     the bjac->x vector is that we need a sequential vector
7164b9ad928SBarry Smith     for the sequential solve.
7174b9ad928SBarry Smith   */
7185f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(x,&x_array));
7195f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(y,&y_array));
7205f80ce2aSJacob Faibussowitsch   CHKERRQ(VecPlaceArray(bjac->x,x_array));
7215f80ce2aSJacob Faibussowitsch   CHKERRQ(VecPlaceArray(bjac->y,y_array));
7225f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPSolveTranspose(jac->ksp[0],bjac->x,bjac->y));
7235f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPCheckSolve(jac->ksp[0],pc,bjac->y));
7245f80ce2aSJacob Faibussowitsch   CHKERRQ(VecResetArray(bjac->x));
7255f80ce2aSJacob Faibussowitsch   CHKERRQ(VecResetArray(bjac->y));
7265f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(x,&x_array));
7275f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(y,&y_array));
7284b9ad928SBarry Smith   PetscFunctionReturn(0);
7294b9ad928SBarry Smith }
7304b9ad928SBarry Smith 
7316849ba73SBarry Smith static PetscErrorCode PCSetUp_BJacobi_Singleblock(PC pc,Mat mat,Mat pmat)
7324b9ad928SBarry Smith {
7334b9ad928SBarry Smith   PC_BJacobi             *jac = (PC_BJacobi*)pc->data;
73469a612a9SBarry Smith   PetscInt               m;
7354b9ad928SBarry Smith   KSP                    ksp;
7364b9ad928SBarry Smith   PC_BJacobi_Singleblock *bjac;
737de0953f6SBarry Smith   PetscBool              wasSetup = PETSC_TRUE;
7383f6dc190SJunchao Zhang   VecType                vectype;
739ea41da7aSPierre Jolivet   const char             *prefix;
7404b9ad928SBarry Smith 
7414b9ad928SBarry Smith   PetscFunctionBegin;
7424b9ad928SBarry Smith   if (!pc->setupcalled) {
743c2efdce3SBarry Smith     if (!jac->ksp) {
744302a9ddcSMatthew Knepley       wasSetup = PETSC_FALSE;
7452fa5cd67SKarl Rupp 
7465f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPCreate(PETSC_COMM_SELF,&ksp));
7475f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPSetErrorIfNotConverged(ksp,pc->erroriffailure));
7485f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,1));
7495f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogObjectParent((PetscObject)pc,(PetscObject)ksp));
7505f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPSetType(ksp,KSPPREONLY));
7515f80ce2aSJacob Faibussowitsch       CHKERRQ(PCGetOptionsPrefix(pc,&prefix));
7525f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPSetOptionsPrefix(ksp,prefix));
7535f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPAppendOptionsPrefix(ksp,"sub_"));
7544b9ad928SBarry Smith 
755e91c6855SBarry Smith       pc->ops->reset               = PCReset_BJacobi_Singleblock;
7564b9ad928SBarry Smith       pc->ops->destroy             = PCDestroy_BJacobi_Singleblock;
7574b9ad928SBarry Smith       pc->ops->apply               = PCApply_BJacobi_Singleblock;
7587b6e2003SPierre Jolivet       pc->ops->matapply            = PCMatApply_BJacobi_Singleblock;
7594b9ad928SBarry Smith       pc->ops->applysymmetricleft  = PCApplySymmetricLeft_BJacobi_Singleblock;
7604b9ad928SBarry Smith       pc->ops->applysymmetricright = PCApplySymmetricRight_BJacobi_Singleblock;
7614b9ad928SBarry Smith       pc->ops->applytranspose      = PCApplyTranspose_BJacobi_Singleblock;
7624b9ad928SBarry Smith       pc->ops->setuponblocks       = PCSetUpOnBlocks_BJacobi_Singleblock;
7634b9ad928SBarry Smith 
7645f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(1,&jac->ksp));
7654b9ad928SBarry Smith       jac->ksp[0] = ksp;
766c2efdce3SBarry Smith 
7675f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscNewLog(pc,&bjac));
7684b9ad928SBarry Smith       jac->data = (void*)bjac;
7694b9ad928SBarry Smith     } else {
770c2efdce3SBarry Smith       ksp  = jac->ksp[0];
771c2efdce3SBarry Smith       bjac = (PC_BJacobi_Singleblock*)jac->data;
772c2efdce3SBarry Smith     }
773c2efdce3SBarry Smith 
774c2efdce3SBarry Smith     /*
775c2efdce3SBarry Smith       The reason we need to generate these vectors is to serve
776c2efdce3SBarry Smith       as the right-hand side and solution vector for the solve on the
777c2efdce3SBarry Smith       block. We do not need to allocate space for the vectors since
778c2efdce3SBarry Smith       that is provided via VecPlaceArray() just before the call to
779c2efdce3SBarry Smith       KSPSolve() on the block.
780c2efdce3SBarry Smith     */
7815f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetSize(pmat,&m,&m));
7825f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCreateSeqWithArray(PETSC_COMM_SELF,1,m,NULL,&bjac->x));
7835f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCreateSeqWithArray(PETSC_COMM_SELF,1,m,NULL,&bjac->y));
7845f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetVecType(pmat,&vectype));
7855f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSetType(bjac->x,vectype));
7865f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSetType(bjac->y,vectype));
7875f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogObjectParent((PetscObject)pc,(PetscObject)bjac->x));
7885f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogObjectParent((PetscObject)pc,(PetscObject)bjac->y));
789c2efdce3SBarry Smith   } else {
7904b9ad928SBarry Smith     ksp  = jac->ksp[0];
7914b9ad928SBarry Smith     bjac = (PC_BJacobi_Singleblock*)jac->data;
7924b9ad928SBarry Smith   }
7935f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPGetOptionsPrefix(ksp,&prefix));
79449517cdeSBarry Smith   if (pc->useAmat) {
7955f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPSetOperators(ksp,mat,pmat));
7965f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetOptionsPrefix(mat,prefix));
7974b9ad928SBarry Smith   } else {
7985f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPSetOperators(ksp,pmat,pmat));
7994b9ad928SBarry Smith   }
8005f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetOptionsPrefix(pmat,prefix));
80190f1c854SHong Zhang   if (!wasSetup && pc->setfromoptionscalled) {
802248bfaf0SJed Brown     /* If PCSetFromOptions_BJacobi is called later, KSPSetFromOptions will be called at that time. */
8035f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPSetFromOptions(ksp));
804302a9ddcSMatthew Knepley   }
8054b9ad928SBarry Smith   PetscFunctionReturn(0);
8064b9ad928SBarry Smith }
8074b9ad928SBarry Smith 
8084b9ad928SBarry Smith /* ---------------------------------------------------------------------------------------------*/
80981f0254dSBarry Smith static PetscErrorCode PCReset_BJacobi_Multiblock(PC pc)
8104b9ad928SBarry Smith {
8114b9ad928SBarry Smith   PC_BJacobi            *jac  = (PC_BJacobi*)pc->data;
8124b9ad928SBarry Smith   PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data;
81369a612a9SBarry Smith   PetscInt              i;
8144b9ad928SBarry Smith 
8154b9ad928SBarry Smith   PetscFunctionBegin;
816e91c6855SBarry Smith   if (bjac && bjac->pmat) {
8175f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroyMatrices(jac->n_local,&bjac->pmat));
81849517cdeSBarry Smith     if (pc->useAmat) {
8195f80ce2aSJacob Faibussowitsch       CHKERRQ(MatDestroyMatrices(jac->n_local,&bjac->mat));
8204b9ad928SBarry Smith     }
821e91c6855SBarry Smith   }
8224b9ad928SBarry Smith 
8234b9ad928SBarry Smith   for (i=0; i<jac->n_local; i++) {
8245f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPReset(jac->ksp[i]));
825e91c6855SBarry Smith     if (bjac && bjac->x) {
8265f80ce2aSJacob Faibussowitsch       CHKERRQ(VecDestroy(&bjac->x[i]));
8275f80ce2aSJacob Faibussowitsch       CHKERRQ(VecDestroy(&bjac->y[i]));
8285f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&bjac->is[i]));
8294b9ad928SBarry Smith     }
830e91c6855SBarry Smith   }
8315f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(jac->l_lens));
8325f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(jac->g_lens));
833e91c6855SBarry Smith   PetscFunctionReturn(0);
834e91c6855SBarry Smith }
835e91c6855SBarry Smith 
83681f0254dSBarry Smith static PetscErrorCode PCDestroy_BJacobi_Multiblock(PC pc)
837e91c6855SBarry Smith {
838e91c6855SBarry Smith   PC_BJacobi            *jac  = (PC_BJacobi*)pc->data;
839c2efdce3SBarry Smith   PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data;
840e91c6855SBarry Smith   PetscInt              i;
841e91c6855SBarry Smith 
842e91c6855SBarry Smith   PetscFunctionBegin;
8435f80ce2aSJacob Faibussowitsch   CHKERRQ(PCReset_BJacobi_Multiblock(pc));
844c2efdce3SBarry Smith   if (bjac) {
8455f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree2(bjac->x,bjac->y));
8465f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(bjac->starts));
8475f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(bjac->is));
848c2efdce3SBarry Smith   }
8495f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(jac->data));
850e91c6855SBarry Smith   for (i=0; i<jac->n_local; i++) {
8515f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPDestroy(&jac->ksp[i]));
852e91c6855SBarry Smith   }
8535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(jac->ksp));
8545f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(pc->data));
8554b9ad928SBarry Smith   PetscFunctionReturn(0);
8564b9ad928SBarry Smith }
8574b9ad928SBarry Smith 
85881f0254dSBarry Smith static PetscErrorCode PCSetUpOnBlocks_BJacobi_Multiblock(PC pc)
8594b9ad928SBarry Smith {
8604b9ad928SBarry Smith   PC_BJacobi         *jac = (PC_BJacobi*)pc->data;
86169a612a9SBarry Smith   PetscInt           i,n_local = jac->n_local;
862539c167fSBarry Smith   KSPConvergedReason reason;
8634b9ad928SBarry Smith 
8644b9ad928SBarry Smith   PetscFunctionBegin;
8654b9ad928SBarry Smith   for (i=0; i<n_local; i++) {
8665f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPSetUp(jac->ksp[i]));
8675f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPGetConvergedReason(jac->ksp[i],&reason));
868c0decd05SBarry Smith     if (reason == KSP_DIVERGED_PC_FAILED) {
869261222b2SHong Zhang       pc->failedreason = PC_SUBPC_ERROR;
8702295b7c8SHong Zhang     }
8714b9ad928SBarry Smith   }
8724b9ad928SBarry Smith   PetscFunctionReturn(0);
8734b9ad928SBarry Smith }
8744b9ad928SBarry Smith 
8754b9ad928SBarry Smith /*
8764b9ad928SBarry Smith       Preconditioner for block Jacobi
8774b9ad928SBarry Smith */
87881f0254dSBarry Smith static PetscErrorCode PCApply_BJacobi_Multiblock(PC pc,Vec x,Vec y)
8794b9ad928SBarry Smith {
8804b9ad928SBarry Smith   PC_BJacobi            *jac = (PC_BJacobi*)pc->data;
88169a612a9SBarry Smith   PetscInt              i,n_local = jac->n_local;
8824b9ad928SBarry Smith   PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data;
883d9ca1df4SBarry Smith   PetscScalar           *yin;
884d9ca1df4SBarry Smith   const PetscScalar     *xin;
88558ebbce7SBarry Smith 
8864b9ad928SBarry Smith   PetscFunctionBegin;
8875f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(x,&xin));
8885f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(y,&yin));
8894b9ad928SBarry Smith   for (i=0; i<n_local; i++) {
8904b9ad928SBarry Smith     /*
8914b9ad928SBarry Smith        To avoid copying the subvector from x into a workspace we instead
8924b9ad928SBarry Smith        make the workspace vector array point to the subpart of the array of
8934b9ad928SBarry Smith        the global vector.
8944b9ad928SBarry Smith     */
8955f80ce2aSJacob Faibussowitsch     CHKERRQ(VecPlaceArray(bjac->x[i],xin+bjac->starts[i]));
8965f80ce2aSJacob Faibussowitsch     CHKERRQ(VecPlaceArray(bjac->y[i],yin+bjac->starts[i]));
8974b9ad928SBarry Smith 
8985f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogEventBegin(PC_ApplyOnBlocks,jac->ksp[i],bjac->x[i],bjac->y[i],0));
8995f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPSolve(jac->ksp[i],bjac->x[i],bjac->y[i]));
9005f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPCheckSolve(jac->ksp[i],pc,bjac->y[i]));
9015f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogEventEnd(PC_ApplyOnBlocks,jac->ksp[i],bjac->x[i],bjac->y[i],0));
902d11f3a42SBarry Smith 
9035f80ce2aSJacob Faibussowitsch     CHKERRQ(VecResetArray(bjac->x[i]));
9045f80ce2aSJacob Faibussowitsch     CHKERRQ(VecResetArray(bjac->y[i]));
9054b9ad928SBarry Smith   }
9065f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(x,&xin));
9075f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(y,&yin));
9084b9ad928SBarry Smith   PetscFunctionReturn(0);
9094b9ad928SBarry Smith }
9104b9ad928SBarry Smith 
9114b9ad928SBarry Smith /*
9124b9ad928SBarry Smith       Preconditioner for block Jacobi
9134b9ad928SBarry Smith */
91481f0254dSBarry Smith static PetscErrorCode PCApplyTranspose_BJacobi_Multiblock(PC pc,Vec x,Vec y)
9154b9ad928SBarry Smith {
9164b9ad928SBarry Smith   PC_BJacobi            *jac = (PC_BJacobi*)pc->data;
91769a612a9SBarry Smith   PetscInt              i,n_local = jac->n_local;
9184b9ad928SBarry Smith   PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data;
919d9ca1df4SBarry Smith   PetscScalar           *yin;
920d9ca1df4SBarry Smith   const PetscScalar     *xin;
9214b9ad928SBarry Smith 
9224b9ad928SBarry Smith   PetscFunctionBegin;
9235f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(x,&xin));
9245f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(y,&yin));
9254b9ad928SBarry Smith   for (i=0; i<n_local; i++) {
9264b9ad928SBarry Smith     /*
9274b9ad928SBarry Smith        To avoid copying the subvector from x into a workspace we instead
9284b9ad928SBarry Smith        make the workspace vector array point to the subpart of the array of
9294b9ad928SBarry Smith        the global vector.
9304b9ad928SBarry Smith     */
9315f80ce2aSJacob Faibussowitsch     CHKERRQ(VecPlaceArray(bjac->x[i],xin+bjac->starts[i]));
9325f80ce2aSJacob Faibussowitsch     CHKERRQ(VecPlaceArray(bjac->y[i],yin+bjac->starts[i]));
9334b9ad928SBarry Smith 
9345f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogEventBegin(PC_ApplyTransposeOnBlocks,jac->ksp[i],bjac->x[i],bjac->y[i],0));
9355f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPSolveTranspose(jac->ksp[i],bjac->x[i],bjac->y[i]));
9365f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPCheckSolve(jac->ksp[i],pc,bjac->y[i]));
9375f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogEventEnd(PC_ApplyTransposeOnBlocks,jac->ksp[i],bjac->x[i],bjac->y[i],0));
938a7ff49e8SJed Brown 
9395f80ce2aSJacob Faibussowitsch     CHKERRQ(VecResetArray(bjac->x[i]));
9405f80ce2aSJacob Faibussowitsch     CHKERRQ(VecResetArray(bjac->y[i]));
9414b9ad928SBarry Smith   }
9425f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(x,&xin));
9435f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(y,&yin));
9444b9ad928SBarry Smith   PetscFunctionReturn(0);
9454b9ad928SBarry Smith }
9464b9ad928SBarry Smith 
9476849ba73SBarry Smith static PetscErrorCode PCSetUp_BJacobi_Multiblock(PC pc,Mat mat,Mat pmat)
9484b9ad928SBarry Smith {
9494b9ad928SBarry Smith   PC_BJacobi            *jac = (PC_BJacobi*)pc->data;
95069a612a9SBarry Smith   PetscInt              m,n_local,N,M,start,i;
951ea41da7aSPierre Jolivet   const char            *prefix;
9524b9ad928SBarry Smith   KSP                   ksp;
9534b9ad928SBarry Smith   Vec                   x,y;
9544b9ad928SBarry Smith   PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data;
9554b9ad928SBarry Smith   PC                    subpc;
9564b9ad928SBarry Smith   IS                    is;
957434a97beSBrad Aagaard   MatReuse              scall;
9583f6dc190SJunchao Zhang   VecType               vectype;
9594b9ad928SBarry Smith 
9604b9ad928SBarry Smith   PetscFunctionBegin;
9615f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetLocalSize(pc->pmat,&M,&N));
9624b9ad928SBarry Smith 
9634b9ad928SBarry Smith   n_local = jac->n_local;
9644b9ad928SBarry Smith 
96549517cdeSBarry Smith   if (pc->useAmat) {
966ace3abfcSBarry Smith     PetscBool same;
9675f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectTypeCompare((PetscObject)mat,((PetscObject)pmat)->type_name,&same));
968*28b400f6SJacob Faibussowitsch     PetscCheck(same,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Matrices not of same type");
9694b9ad928SBarry Smith   }
9704b9ad928SBarry Smith 
9714b9ad928SBarry Smith   if (!pc->setupcalled) {
9724b9ad928SBarry Smith     scall = MAT_INITIAL_MATRIX;
973c2efdce3SBarry Smith 
974c2efdce3SBarry Smith     if (!jac->ksp) {
975e91c6855SBarry Smith       pc->ops->reset         = PCReset_BJacobi_Multiblock;
9764b9ad928SBarry Smith       pc->ops->destroy       = PCDestroy_BJacobi_Multiblock;
9774b9ad928SBarry Smith       pc->ops->apply         = PCApply_BJacobi_Multiblock;
9787b6e2003SPierre Jolivet       pc->ops->matapply      = NULL;
9794b9ad928SBarry Smith       pc->ops->applytranspose= PCApplyTranspose_BJacobi_Multiblock;
9804b9ad928SBarry Smith       pc->ops->setuponblocks = PCSetUpOnBlocks_BJacobi_Multiblock;
9814b9ad928SBarry Smith 
9825f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscNewLog(pc,&bjac));
9835f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(n_local,&jac->ksp));
9845f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogObjectMemory((PetscObject)pc,sizeof(n_local*sizeof(KSP))));
9855f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc2(n_local,&bjac->x,n_local,&bjac->y));
9865f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(n_local,&bjac->starts));
9875f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogObjectMemory((PetscObject)pc,sizeof(n_local*sizeof(PetscScalar))));
9884b9ad928SBarry Smith 
9894b9ad928SBarry Smith       jac->data = (void*)bjac;
9905f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(n_local,&bjac->is));
9915f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogObjectMemory((PetscObject)pc,sizeof(n_local*sizeof(IS))));
9924b9ad928SBarry Smith 
9934b9ad928SBarry Smith       for (i=0; i<n_local; i++) {
9945f80ce2aSJacob Faibussowitsch         CHKERRQ(KSPCreate(PETSC_COMM_SELF,&ksp));
9955f80ce2aSJacob Faibussowitsch         CHKERRQ(KSPSetErrorIfNotConverged(ksp,pc->erroriffailure));
9965f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,1));
9975f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscLogObjectParent((PetscObject)pc,(PetscObject)ksp));
9985f80ce2aSJacob Faibussowitsch         CHKERRQ(KSPSetType(ksp,KSPPREONLY));
9995f80ce2aSJacob Faibussowitsch         CHKERRQ(KSPGetPC(ksp,&subpc));
10005f80ce2aSJacob Faibussowitsch         CHKERRQ(PCGetOptionsPrefix(pc,&prefix));
10015f80ce2aSJacob Faibussowitsch         CHKERRQ(KSPSetOptionsPrefix(ksp,prefix));
10025f80ce2aSJacob Faibussowitsch         CHKERRQ(KSPAppendOptionsPrefix(ksp,"sub_"));
10032fa5cd67SKarl Rupp 
1004c2efdce3SBarry Smith         jac->ksp[i] = ksp;
1005c2efdce3SBarry Smith       }
1006c2efdce3SBarry Smith     } else {
1007c2efdce3SBarry Smith       bjac = (PC_BJacobi_Multiblock*)jac->data;
1008c2efdce3SBarry Smith     }
10094b9ad928SBarry Smith 
1010c2efdce3SBarry Smith     start = 0;
10115f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetVecType(pmat,&vectype));
1012c2efdce3SBarry Smith     for (i=0; i<n_local; i++) {
10134b9ad928SBarry Smith       m = jac->l_lens[i];
10144b9ad928SBarry Smith       /*
10154b9ad928SBarry Smith       The reason we need to generate these vectors is to serve
10164b9ad928SBarry Smith       as the right-hand side and solution vector for the solve on the
10174b9ad928SBarry Smith       block. We do not need to allocate space for the vectors since
10184b9ad928SBarry Smith       that is provided via VecPlaceArray() just before the call to
10194b9ad928SBarry Smith       KSPSolve() on the block.
10204b9ad928SBarry Smith 
10214b9ad928SBarry Smith       */
10225f80ce2aSJacob Faibussowitsch       CHKERRQ(VecCreateSeq(PETSC_COMM_SELF,m,&x));
10235f80ce2aSJacob Faibussowitsch       CHKERRQ(VecCreateSeqWithArray(PETSC_COMM_SELF,1,m,NULL,&y));
10245f80ce2aSJacob Faibussowitsch       CHKERRQ(VecSetType(x,vectype));
10255f80ce2aSJacob Faibussowitsch       CHKERRQ(VecSetType(y,vectype));
10265f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogObjectParent((PetscObject)pc,(PetscObject)x));
10275f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogObjectParent((PetscObject)pc,(PetscObject)y));
10282fa5cd67SKarl Rupp 
10294b9ad928SBarry Smith       bjac->x[i]      = x;
10304b9ad928SBarry Smith       bjac->y[i]      = y;
10314b9ad928SBarry Smith       bjac->starts[i] = start;
10324b9ad928SBarry Smith 
10335f80ce2aSJacob Faibussowitsch       CHKERRQ(ISCreateStride(PETSC_COMM_SELF,m,start,1,&is));
10344b9ad928SBarry Smith       bjac->is[i] = is;
10355f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogObjectParent((PetscObject)pc,(PetscObject)is));
10364b9ad928SBarry Smith 
10374b9ad928SBarry Smith       start += m;
10384b9ad928SBarry Smith     }
10394b9ad928SBarry Smith   } else {
10404b9ad928SBarry Smith     bjac = (PC_BJacobi_Multiblock*)jac->data;
10414b9ad928SBarry Smith     /*
10424b9ad928SBarry Smith        Destroy the blocks from the previous iteration
10434b9ad928SBarry Smith     */
10444b9ad928SBarry Smith     if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
10455f80ce2aSJacob Faibussowitsch       CHKERRQ(MatDestroyMatrices(n_local,&bjac->pmat));
104649517cdeSBarry Smith       if (pc->useAmat) {
10475f80ce2aSJacob Faibussowitsch         CHKERRQ(MatDestroyMatrices(n_local,&bjac->mat));
10484b9ad928SBarry Smith       }
10494b9ad928SBarry Smith       scall = MAT_INITIAL_MATRIX;
10502fa5cd67SKarl Rupp     } else scall = MAT_REUSE_MATRIX;
10514b9ad928SBarry Smith   }
10524b9ad928SBarry Smith 
10535f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateSubMatrices(pmat,n_local,bjac->is,bjac->is,scall,&bjac->pmat));
105449517cdeSBarry Smith   if (pc->useAmat) {
10555f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreateSubMatrices(mat,n_local,bjac->is,bjac->is,scall,&bjac->mat));
10564b9ad928SBarry Smith   }
10574b9ad928SBarry Smith   /* Return control to the user so that the submatrices can be modified (e.g., to apply
10584b9ad928SBarry Smith      different boundary conditions for the submatrices than for the global problem) */
10595f80ce2aSJacob Faibussowitsch   CHKERRQ(PCModifySubMatrices(pc,n_local,bjac->is,bjac->is,bjac->pmat,pc->modifysubmatricesP));
10604b9ad928SBarry Smith 
10614b9ad928SBarry Smith   for (i=0; i<n_local; i++) {
10625f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogObjectParent((PetscObject)pc,(PetscObject)bjac->pmat[i]));
10635f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPGetOptionsPrefix(jac->ksp[i],&prefix));
106449517cdeSBarry Smith     if (pc->useAmat) {
10655f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogObjectParent((PetscObject)pc,(PetscObject)bjac->mat[i]));
10665f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPSetOperators(jac->ksp[i],bjac->mat[i],bjac->pmat[i]));
10675f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetOptionsPrefix(bjac->mat[i],prefix));
10684b9ad928SBarry Smith     } else {
10695f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPSetOperators(jac->ksp[i],bjac->pmat[i],bjac->pmat[i]));
10704b9ad928SBarry Smith     }
10715f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetOptionsPrefix(bjac->pmat[i],prefix));
107290f1c854SHong Zhang     if (pc->setfromoptionscalled) {
10735f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPSetFromOptions(jac->ksp[i]));
10744b9ad928SBarry Smith     }
107590f1c854SHong Zhang   }
10764b9ad928SBarry Smith   PetscFunctionReturn(0);
10774b9ad928SBarry Smith }
10785a7e1895SHong Zhang 
10795a7e1895SHong Zhang /* ---------------------------------------------------------------------------------------------*/
10805a7e1895SHong Zhang /*
1081fd0b8932SBarry Smith       These are for a single block with multiple processes
10825a7e1895SHong Zhang */
1083fd0b8932SBarry Smith static PetscErrorCode PCSetUpOnBlocks_BJacobi_Multiproc(PC pc)
1084fd0b8932SBarry Smith {
1085fd0b8932SBarry Smith   PC_BJacobi         *jac = (PC_BJacobi*)pc->data;
1086fd0b8932SBarry Smith   KSP                subksp = jac->ksp[0];
1087fd0b8932SBarry Smith   KSPConvergedReason reason;
1088fd0b8932SBarry Smith 
1089fd0b8932SBarry Smith   PetscFunctionBegin;
10905f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPSetUp(subksp));
10915f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPGetConvergedReason(subksp,&reason));
1092fd0b8932SBarry Smith   if (reason == KSP_DIVERGED_PC_FAILED) {
1093fd0b8932SBarry Smith     pc->failedreason = PC_SUBPC_ERROR;
1094fd0b8932SBarry Smith   }
1095fd0b8932SBarry Smith   PetscFunctionReturn(0);
1096fd0b8932SBarry Smith }
1097fd0b8932SBarry Smith 
1098e91c6855SBarry Smith static PetscErrorCode PCReset_BJacobi_Multiproc(PC pc)
10995a7e1895SHong Zhang {
11005a7e1895SHong Zhang   PC_BJacobi           *jac   = (PC_BJacobi*)pc->data;
11015a7e1895SHong Zhang   PC_BJacobi_Multiproc *mpjac = (PC_BJacobi_Multiproc*)jac->data;
11025a7e1895SHong Zhang 
11035a7e1895SHong Zhang   PetscFunctionBegin;
11045f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&mpjac->ysub));
11055f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&mpjac->xsub));
11065f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&mpjac->submats));
11075f80ce2aSJacob Faibussowitsch   if (jac->ksp) CHKERRQ(KSPReset(jac->ksp[0]));
1108e91c6855SBarry Smith   PetscFunctionReturn(0);
1109e91c6855SBarry Smith }
1110e91c6855SBarry Smith 
1111e91c6855SBarry Smith static PetscErrorCode PCDestroy_BJacobi_Multiproc(PC pc)
1112e91c6855SBarry Smith {
1113e91c6855SBarry Smith   PC_BJacobi           *jac   = (PC_BJacobi*)pc->data;
1114e91c6855SBarry Smith   PC_BJacobi_Multiproc *mpjac = (PC_BJacobi_Multiproc*)jac->data;
1115e91c6855SBarry Smith 
1116e91c6855SBarry Smith   PetscFunctionBegin;
11175f80ce2aSJacob Faibussowitsch   CHKERRQ(PCReset_BJacobi_Multiproc(pc));
11185f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPDestroy(&jac->ksp[0]));
11195f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(jac->ksp));
11205f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSubcommDestroy(&mpjac->psubcomm));
11215a7e1895SHong Zhang 
11225f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(mpjac));
11235f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(pc->data));
11245a7e1895SHong Zhang   PetscFunctionReturn(0);
11255a7e1895SHong Zhang }
11265a7e1895SHong Zhang 
11275a7e1895SHong Zhang static PetscErrorCode PCApply_BJacobi_Multiproc(PC pc,Vec x,Vec y)
11285a7e1895SHong Zhang {
11295a7e1895SHong Zhang   PC_BJacobi           *jac   = (PC_BJacobi*)pc->data;
11305a7e1895SHong Zhang   PC_BJacobi_Multiproc *mpjac = (PC_BJacobi_Multiproc*)jac->data;
1131d9ca1df4SBarry Smith   PetscScalar          *yarray;
1132d9ca1df4SBarry Smith   const PetscScalar    *xarray;
1133539c167fSBarry Smith   KSPConvergedReason   reason;
11345a7e1895SHong Zhang 
11355a7e1895SHong Zhang   PetscFunctionBegin;
11365a7e1895SHong Zhang   /* place x's and y's local arrays into xsub and ysub */
11375f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(x,&xarray));
11385f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(y,&yarray));
11395f80ce2aSJacob Faibussowitsch   CHKERRQ(VecPlaceArray(mpjac->xsub,xarray));
11405f80ce2aSJacob Faibussowitsch   CHKERRQ(VecPlaceArray(mpjac->ysub,yarray));
11415a7e1895SHong Zhang 
11425a7e1895SHong Zhang   /* apply preconditioner on each matrix block */
11435f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(PC_ApplyOnBlocks,jac->ksp[0],mpjac->xsub,mpjac->ysub,0));
11445f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPSolve(jac->ksp[0],mpjac->xsub,mpjac->ysub));
11455f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPCheckSolve(jac->ksp[0],pc,mpjac->ysub));
11465f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(PC_ApplyOnBlocks,jac->ksp[0],mpjac->xsub,mpjac->ysub,0));
11475f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPGetConvergedReason(jac->ksp[0],&reason));
1148c0decd05SBarry Smith   if (reason == KSP_DIVERGED_PC_FAILED) {
1149261222b2SHong Zhang     pc->failedreason = PC_SUBPC_ERROR;
1150250cf88bSHong Zhang   }
1151250cf88bSHong Zhang 
11525f80ce2aSJacob Faibussowitsch   CHKERRQ(VecResetArray(mpjac->xsub));
11535f80ce2aSJacob Faibussowitsch   CHKERRQ(VecResetArray(mpjac->ysub));
11545f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(x,&xarray));
11555f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(y,&yarray));
11565a7e1895SHong Zhang   PetscFunctionReturn(0);
11575a7e1895SHong Zhang }
11585a7e1895SHong Zhang 
11597b6e2003SPierre Jolivet static PetscErrorCode PCMatApply_BJacobi_Multiproc(PC pc,Mat X,Mat Y)
11607b6e2003SPierre Jolivet {
11617b6e2003SPierre Jolivet   PC_BJacobi           *jac   = (PC_BJacobi*)pc->data;
11627b6e2003SPierre Jolivet   KSPConvergedReason   reason;
11637b6e2003SPierre Jolivet   Mat                  sX,sY;
11647b6e2003SPierre Jolivet   const PetscScalar    *x;
11657b6e2003SPierre Jolivet   PetscScalar          *y;
11667b6e2003SPierre Jolivet   PetscInt             m,N,lda,ldb;
11677b6e2003SPierre Jolivet 
11687b6e2003SPierre Jolivet   PetscFunctionBegin;
11697b6e2003SPierre Jolivet   /* apply preconditioner on each matrix block */
11705f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetLocalSize(X,&m,NULL));
11715f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(X,NULL,&N));
11725f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDenseGetLDA(X,&lda));
11735f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDenseGetLDA(Y,&ldb));
11745f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDenseGetArrayRead(X,&x));
11755f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDenseGetArrayWrite(Y,&y));
11765f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateDense(PetscObjectComm((PetscObject)jac->ksp[0]),m,PETSC_DECIDE,PETSC_DECIDE,N,(PetscScalar*)x,&sX));
11775f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateDense(PetscObjectComm((PetscObject)jac->ksp[0]),m,PETSC_DECIDE,PETSC_DECIDE,N,y,&sY));
11785f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDenseSetLDA(sX,lda));
11795f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDenseSetLDA(sY,ldb));
11805f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(PC_ApplyOnBlocks,jac->ksp[0],X,Y,0));
11815f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPMatSolve(jac->ksp[0],sX,sY));
11825f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPCheckSolve(jac->ksp[0],pc,NULL));
11835f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(PC_ApplyOnBlocks,jac->ksp[0],X,Y,0));
11845f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&sY));
11855f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&sX));
11865f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDenseRestoreArrayWrite(Y,&y));
11875f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDenseRestoreArrayRead(X,&x));
11885f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPGetConvergedReason(jac->ksp[0],&reason));
11897b6e2003SPierre Jolivet   if (reason == KSP_DIVERGED_PC_FAILED) {
11907b6e2003SPierre Jolivet     pc->failedreason = PC_SUBPC_ERROR;
11917b6e2003SPierre Jolivet   }
11927b6e2003SPierre Jolivet   PetscFunctionReturn(0);
11937b6e2003SPierre Jolivet }
11947b6e2003SPierre Jolivet 
11955a7e1895SHong Zhang static PetscErrorCode PCSetUp_BJacobi_Multiproc(PC pc)
11965a7e1895SHong Zhang {
11975a7e1895SHong Zhang   PC_BJacobi           *jac   = (PC_BJacobi*)pc->data;
11985a7e1895SHong Zhang   PC_BJacobi_Multiproc *mpjac = (PC_BJacobi_Multiproc*)jac->data;
11995a7e1895SHong Zhang   PetscInt             m,n;
1200ce94432eSBarry Smith   MPI_Comm             comm,subcomm=0;
12015a7e1895SHong Zhang   const char           *prefix;
1202de0953f6SBarry Smith   PetscBool            wasSetup = PETSC_TRUE;
12033f6dc190SJunchao Zhang   VecType              vectype;
12041f62890fSKarl Rupp 
12055a7e1895SHong Zhang   PetscFunctionBegin;
12065f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)pc,&comm));
12072c71b3e2SJacob Faibussowitsch   PetscCheckFalse(jac->n_local > 1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Only a single block in a subcommunicator is supported");
12085a7e1895SHong Zhang   jac->n_local = 1; /* currently only a single block is supported for a subcommunicator */
12095a7e1895SHong Zhang   if (!pc->setupcalled) {
1210de0953f6SBarry Smith     wasSetup  = PETSC_FALSE;
12115f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscNewLog(pc,&mpjac));
12125a7e1895SHong Zhang     jac->data = (void*)mpjac;
12135a7e1895SHong Zhang 
12145a7e1895SHong Zhang     /* initialize datastructure mpjac */
12155a7e1895SHong Zhang     if (!jac->psubcomm) {
12165a7e1895SHong Zhang       /* Create default contiguous subcommunicatiors if user does not provide them */
12175f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSubcommCreate(comm,&jac->psubcomm));
12185f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSubcommSetNumber(jac->psubcomm,jac->n));
12195f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSubcommSetType(jac->psubcomm,PETSC_SUBCOMM_CONTIGUOUS));
12205f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogObjectMemory((PetscObject)pc,sizeof(PetscSubcomm)));
12215a7e1895SHong Zhang     }
12225a7e1895SHong Zhang     mpjac->psubcomm = jac->psubcomm;
1223306c2d5bSBarry Smith     subcomm         = PetscSubcommChild(mpjac->psubcomm);
12245a7e1895SHong Zhang 
12255a7e1895SHong Zhang     /* Get matrix blocks of pmat */
12265f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetMultiProcBlock(pc->pmat,subcomm,MAT_INITIAL_MATRIX,&mpjac->submats));
12275a7e1895SHong Zhang 
12285a7e1895SHong Zhang     /* create a new PC that processors in each subcomm have copy of */
12295f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(1,&jac->ksp));
12305f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPCreate(subcomm,&jac->ksp[0]));
12315f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPSetErrorIfNotConverged(jac->ksp[0],pc->erroriffailure));
12325f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectIncrementTabLevel((PetscObject)jac->ksp[0],(PetscObject)pc,1));
12335f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->ksp[0]));
12345f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPSetOperators(jac->ksp[0],mpjac->submats,mpjac->submats));
12355f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPGetPC(jac->ksp[0],&mpjac->pc));
12365a7e1895SHong Zhang 
12375f80ce2aSJacob Faibussowitsch     CHKERRQ(PCGetOptionsPrefix(pc,&prefix));
12385f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPSetOptionsPrefix(jac->ksp[0],prefix));
12395f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPAppendOptionsPrefix(jac->ksp[0],"sub_"));
12405f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPGetOptionsPrefix(jac->ksp[0],&prefix));
12415f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetOptionsPrefix(mpjac->submats,prefix));
12425a7e1895SHong Zhang 
12435a7e1895SHong Zhang     /* create dummy vectors xsub and ysub */
12445f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetLocalSize(mpjac->submats,&m,&n));
12455f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCreateMPIWithArray(subcomm,1,n,PETSC_DECIDE,NULL,&mpjac->xsub));
12465f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCreateMPIWithArray(subcomm,1,m,PETSC_DECIDE,NULL,&mpjac->ysub));
12475f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetVecType(mpjac->submats,&vectype));
12485f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSetType(mpjac->xsub,vectype));
12495f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSetType(mpjac->ysub,vectype));
12505f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogObjectParent((PetscObject)pc,(PetscObject)mpjac->xsub));
12515f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogObjectParent((PetscObject)pc,(PetscObject)mpjac->ysub));
12525a7e1895SHong Zhang 
1253fd0b8932SBarry Smith     pc->ops->setuponblocks = PCSetUpOnBlocks_BJacobi_Multiproc;
1254e91c6855SBarry Smith     pc->ops->reset         = PCReset_BJacobi_Multiproc;
12555a7e1895SHong Zhang     pc->ops->destroy       = PCDestroy_BJacobi_Multiproc;
12565a7e1895SHong Zhang     pc->ops->apply         = PCApply_BJacobi_Multiproc;
12577b6e2003SPierre Jolivet     pc->ops->matapply      = PCMatApply_BJacobi_Multiproc;
1258fc08c53fSHong Zhang   } else { /* pc->setupcalled */
1259306c2d5bSBarry Smith     subcomm = PetscSubcommChild(mpjac->psubcomm);
12609e0ae222SHong Zhang     if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
12615a7e1895SHong Zhang       /* destroy old matrix blocks, then get new matrix blocks */
12625f80ce2aSJacob Faibussowitsch       if (mpjac->submats) CHKERRQ(MatDestroy(&mpjac->submats));
12635f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetMultiProcBlock(pc->pmat,subcomm,MAT_INITIAL_MATRIX,&mpjac->submats));
1264fc08c53fSHong Zhang     } else {
12655f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetMultiProcBlock(pc->pmat,subcomm,MAT_REUSE_MATRIX,&mpjac->submats));
12665a7e1895SHong Zhang     }
12675f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPSetOperators(jac->ksp[0],mpjac->submats,mpjac->submats));
12685a7e1895SHong Zhang   }
12695a7e1895SHong Zhang 
1270de0953f6SBarry Smith   if (!wasSetup && pc->setfromoptionscalled) {
12715f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPSetFromOptions(jac->ksp[0]));
12725a7e1895SHong Zhang   }
12735a7e1895SHong Zhang   PetscFunctionReturn(0);
12745a7e1895SHong Zhang }
1275