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; 229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank)); 239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size)); 249566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pc->pmat,&M,&N)); 259566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(pc->pmat,&bs)); 264b9ad928SBarry Smith 275a7e1895SHong Zhang if (jac->n > 0 && jac->n < size) { 289566063dSJacob Faibussowitsch PetscCall(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) { 389566063dSJacob Faibussowitsch PetscCallMPI(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 { 479566063dSJacob Faibussowitsch PetscCall(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++) { 55*7827d75bSBarry Smith PetscCheck(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; 609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(jac->n_local,&jac->l_lens)); 619566063dSJacob Faibussowitsch PetscCall(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 { 679566063dSJacob Faibussowitsch PetscCall(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; 839566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(jac->n_local,&jac->l_lens)); 849566063dSJacob Faibussowitsch PetscCall(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); 889566063dSJacob Faibussowitsch PetscCall(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; 91*7827d75bSBarry Smith PetscCheck(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; 979566063dSJacob Faibussowitsch PetscCall(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) { 1019566063dSJacob Faibussowitsch PetscCall(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 ---------------------------*/ 1109566063dSJacob Faibussowitsch PetscCall(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() */ 1179566063dSJacob Faibussowitsch PetscCall(MatGetDiagonalBlock(pc->mat,&mat)); 1184b9ad928SBarry Smith } 11949517cdeSBarry Smith if (pc->pmat != pc->mat || !pc->useAmat) { 1209566063dSJacob Faibussowitsch PetscCall(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) { 1289566063dSJacob Faibussowitsch PetscCall(PCSetUp_BJacobi_Singleblock(pc,mat,pmat)); 1294b9ad928SBarry Smith } else { 1309566063dSJacob Faibussowitsch PetscCall(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; 1419566063dSJacob Faibussowitsch PetscCall(PetscFree(jac->g_lens)); 1429566063dSJacob Faibussowitsch PetscCall(PetscFree(jac->l_lens)); 1439566063dSJacob Faibussowitsch PetscCall(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; 1549566063dSJacob Faibussowitsch PetscCall(PetscOptionsHead(PetscOptionsObject,"Block Jacobi options")); 1559566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bjacobi_blocks","Total number of blocks","PCBJacobiSetTotalBlocks",jac->n,&blocks,&flg)); 1569566063dSJacob Faibussowitsch if (flg) PetscCall(PCBJacobiSetTotalBlocks(pc,blocks,NULL)); 1579566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bjacobi_local_blocks","Local number of blocks","PCBJacobiSetLocalBlocks",jac->n_local,&blocks,&flg)); 1589566063dSJacob Faibussowitsch if (flg) PetscCall(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++) { 1639566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(jac->ksp[i])); 164248bfaf0SJed Brown } 165248bfaf0SJed Brown } 1669566063dSJacob Faibussowitsch PetscCall(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; 1849566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii)); 1859566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring)); 1869566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw)); 18732077d6dSBarry Smith if (iascii) { 18849517cdeSBarry Smith if (pc->useAmat) { 1899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," using Amat local matrix, number of blocks = %D\n",jac->n)); 1904b9ad928SBarry Smith } 1919566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," number of blocks = %D\n",jac->n)); 1929566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank)); 1939566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer,&format)); 194020d6619SPierre Jolivet if (format != PETSC_VIEWER_ASCII_INFO_DETAIL) { 1959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Local solver information for first block is in the following KSP and PC objects on rank 0:\n")); 1969566063dSJacob Faibussowitsch PetscCall(PCGetOptionsPrefix(pc,&prefix)); 1979566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Use -%sksp_view ::ascii_info_detail to display information for all blocks\n",prefix?prefix:"")); 198933995ecSHong Zhang if (jac->ksp && !jac->psubcomm) { 1999566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer)); 200dd400576SPatrick Sanan if (rank == 0) { 2019566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 2029566063dSJacob Faibussowitsch PetscCall(KSPView(jac->ksp[0],sviewer)); 2039566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 2044b9ad928SBarry Smith } 2059566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(sviewer)); 2069566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer)); 2079566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 208e4de9e1dSBarry Smith /* extra call needed because of the two calls to PetscViewerASCIIPushSynchronized() in PetscViewerGetSubViewer() */ 2099566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 210e4fa1014SBarry Smith } else if (mpjac && jac->ksp && mpjac->psubcomm) { 2119566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer,mpjac->psubcomm->child,&sviewer)); 212e4fa1014SBarry Smith if (!mpjac->psubcomm->color) { 2139566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 2149566063dSJacob Faibussowitsch PetscCall(KSPView(*(jac->ksp),sviewer)); 2159566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 216cbe18068SHong Zhang } 2179566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(sviewer)); 2189566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer,mpjac->psubcomm->child,&sviewer)); 2199566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 2209530cbd7SBarry Smith /* extra call needed because of the two calls to PetscViewerASCIIPushSynchronized() in PetscViewerGetSubViewer() */ 2219566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 2224b9ad928SBarry Smith } else { 2239566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 224e4de9e1dSBarry Smith } 225e4de9e1dSBarry Smith } else { 2264814766eSBarry Smith PetscInt n_global; 2279566063dSJacob Faibussowitsch PetscCallMPI(MPIU_Allreduce(&jac->n_local,&n_global,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc))); 2289566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 2299566063dSJacob Faibussowitsch PetscCall(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", 2319566063dSJacob Faibussowitsch rank,jac->n_local,jac->first_local);PetscCall(ierr); 2329566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 2339566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer)); 234dd2fa690SBarry Smith for (i=0; i<jac->n_local; i++) { 2359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer,"[%d] local block number %D\n",rank,i)); 2369566063dSJacob Faibussowitsch PetscCall(KSPView(jac->ksp[i],sviewer)); 2379566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISynchronizedPrintf(viewer,"- - - - - - - - - - - - - - - - - -\n")); 2384b9ad928SBarry Smith } 2399566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer)); 2409566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 2419566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 2429566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 2434b9ad928SBarry Smith } 2444b9ad928SBarry Smith } else if (isstring) { 2459566063dSJacob Faibussowitsch PetscCall(PetscViewerStringSPrintf(viewer," blks=%D",jac->n)); 2469566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer)); 2479566063dSJacob Faibussowitsch if (jac->ksp) PetscCall(KSPView(jac->ksp[0],sviewer)); 2489566063dSJacob Faibussowitsch PetscCall(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 2549566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer,0,&draw)); 2559566063dSJacob Faibussowitsch PetscCall(PetscDrawGetCurrentPoint(draw,&x,&y)); 2569566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(str,25,"Number blocks %D",jac->n)); 2579566063dSJacob Faibussowitsch PetscCall(PetscDrawStringBoxed(draw,x,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h)); 258d9884438SBarry Smith bottom = y - h; 2599566063dSJacob Faibussowitsch PetscCall(PetscDrawPushCurrentPoint(draw,x,bottom)); 260d9884438SBarry Smith /* warning the communicator on viewer is different then on ksp in parallel */ 2619566063dSJacob Faibussowitsch if (jac->ksp) PetscCall(KSPView(jac->ksp[0],viewer)); 2629566063dSJacob Faibussowitsch PetscCall(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; 27428b400f6SJacob 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 { 2919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(blocks,&jac->g_lens)); 2929566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)pc,blocks*sizeof(PetscInt))); 2939566063dSJacob Faibussowitsch PetscCall(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 { 3189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(blocks,&jac->l_lens)); 3199566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)pc,blocks*sizeof(PetscInt))); 3209566063dSJacob Faibussowitsch PetscCall(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); 3719566063dSJacob Faibussowitsch PetscCall(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"); 4029566063dSJacob Faibussowitsch PetscCall(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); 4289566063dSJacob Faibussowitsch PetscCall(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"); 4589566063dSJacob Faibussowitsch PetscCall(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); 4859566063dSJacob Faibussowitsch PetscCall(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; 5329566063dSJacob Faibussowitsch PetscCall(PetscNewLog(pc,&jac)); 5339566063dSJacob Faibussowitsch PetscCallMPI(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 5539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBJacobiGetSubKSP_C",PCBJacobiGetSubKSP_BJacobi)); 5549566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBJacobiSetTotalBlocks_C",PCBJacobiSetTotalBlocks_BJacobi)); 5559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBJacobiGetTotalBlocks_C",PCBJacobiGetTotalBlocks_BJacobi)); 5569566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBJacobiSetLocalBlocks_C",PCBJacobiSetLocalBlocks_BJacobi)); 5579566063dSJacob Faibussowitsch PetscCall(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; 5719566063dSJacob Faibussowitsch PetscCall(KSPReset(jac->ksp[0])); 5729566063dSJacob Faibussowitsch PetscCall(VecDestroy(&bjac->x)); 5739566063dSJacob Faibussowitsch PetscCall(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; 5839566063dSJacob Faibussowitsch PetscCall(PCReset_BJacobi_Singleblock(pc)); 5849566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&jac->ksp[0])); 5859566063dSJacob Faibussowitsch PetscCall(PetscFree(jac->ksp)); 5869566063dSJacob Faibussowitsch PetscCall(PetscFree(jac->l_lens)); 5879566063dSJacob Faibussowitsch PetscCall(PetscFree(jac->g_lens)); 5889566063dSJacob Faibussowitsch PetscCall(PetscFree(bjac)); 5899566063dSJacob Faibussowitsch PetscCall(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; 6009566063dSJacob Faibussowitsch PetscCall(KSPSetUp(subksp)); 6019566063dSJacob Faibussowitsch PetscCall(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; 6149566063dSJacob Faibussowitsch PetscCall(VecGetLocalVectorRead(x, bjac->x)); 6159566063dSJacob Faibussowitsch PetscCall(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.*/ 6199566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(jac->ksp[0],pc->reusepreconditioner)); 6209566063dSJacob Faibussowitsch PetscCall(KSPSolve(jac->ksp[0],bjac->x,bjac->y)); 6219566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(jac->ksp[0],pc,bjac->y)); 6229566063dSJacob Faibussowitsch PetscCall(VecRestoreLocalVectorRead(x, bjac->x)); 6239566063dSJacob Faibussowitsch PetscCall(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.*/ 6369566063dSJacob Faibussowitsch PetscCall(KSPSetReusePreconditioner(jac->ksp[0],pc->reusepreconditioner)); 6379566063dSJacob Faibussowitsch PetscCall(MatDenseGetLocalMatrix(X,&sX)); 6389566063dSJacob Faibussowitsch PetscCall(MatDenseGetLocalMatrix(Y,&sY)); 6399566063dSJacob Faibussowitsch PetscCall(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 */ 6589566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x,&x_array)); 6599566063dSJacob Faibussowitsch PetscCall(VecGetArray(y,&y_array)); 6609566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(bjac->x,x_array)); 6619566063dSJacob Faibussowitsch PetscCall(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 */ 6649566063dSJacob Faibussowitsch PetscCall(KSPGetPC(jac->ksp[0],&subpc)); 6659566063dSJacob Faibussowitsch PetscCall(PCApplySymmetricLeft(subpc,bjac->x,bjac->y)); 6669566063dSJacob Faibussowitsch PetscCall(VecResetArray(bjac->x)); 6679566063dSJacob Faibussowitsch PetscCall(VecResetArray(bjac->y)); 6689566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x,&x_array)); 6699566063dSJacob Faibussowitsch PetscCall(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 */ 6889566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x,&x_array)); 6899566063dSJacob Faibussowitsch PetscCall(VecGetArray(y,&y_array)); 6909566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(bjac->x,x_array)); 6919566063dSJacob Faibussowitsch PetscCall(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 6969566063dSJacob Faibussowitsch PetscCall(KSPGetPC(jac->ksp[0],&subpc)); 6979566063dSJacob Faibussowitsch PetscCall(PCApplySymmetricRight(subpc,bjac->x,bjac->y)); 6984b9ad928SBarry Smith 6999566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x,&x_array)); 7009566063dSJacob Faibussowitsch PetscCall(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 */ 7189566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x,&x_array)); 7199566063dSJacob Faibussowitsch PetscCall(VecGetArray(y,&y_array)); 7209566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(bjac->x,x_array)); 7219566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(bjac->y,y_array)); 7229566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(jac->ksp[0],bjac->x,bjac->y)); 7239566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(jac->ksp[0],pc,bjac->y)); 7249566063dSJacob Faibussowitsch PetscCall(VecResetArray(bjac->x)); 7259566063dSJacob Faibussowitsch PetscCall(VecResetArray(bjac->y)); 7269566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x,&x_array)); 7279566063dSJacob Faibussowitsch PetscCall(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 7469566063dSJacob Faibussowitsch PetscCall(KSPCreate(PETSC_COMM_SELF,&ksp)); 7479566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(ksp,pc->erroriffailure)); 7489566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,1)); 7499566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)pc,(PetscObject)ksp)); 7509566063dSJacob Faibussowitsch PetscCall(KSPSetType(ksp,KSPPREONLY)); 7519566063dSJacob Faibussowitsch PetscCall(PCGetOptionsPrefix(pc,&prefix)); 7529566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(ksp,prefix)); 7539566063dSJacob Faibussowitsch PetscCall(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 7649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1,&jac->ksp)); 7654b9ad928SBarry Smith jac->ksp[0] = ksp; 766c2efdce3SBarry Smith 7679566063dSJacob Faibussowitsch PetscCall(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 */ 7819566063dSJacob Faibussowitsch PetscCall(MatGetSize(pmat,&m,&m)); 7829566063dSJacob Faibussowitsch PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF,1,m,NULL,&bjac->x)); 7839566063dSJacob Faibussowitsch PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF,1,m,NULL,&bjac->y)); 7849566063dSJacob Faibussowitsch PetscCall(MatGetVecType(pmat,&vectype)); 7859566063dSJacob Faibussowitsch PetscCall(VecSetType(bjac->x,vectype)); 7869566063dSJacob Faibussowitsch PetscCall(VecSetType(bjac->y,vectype)); 7879566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)pc,(PetscObject)bjac->x)); 7889566063dSJacob Faibussowitsch PetscCall(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 } 7939566063dSJacob Faibussowitsch PetscCall(KSPGetOptionsPrefix(ksp,&prefix)); 79449517cdeSBarry Smith if (pc->useAmat) { 7959566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(ksp,mat,pmat)); 7969566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(mat,prefix)); 7974b9ad928SBarry Smith } else { 7989566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(ksp,pmat,pmat)); 7994b9ad928SBarry Smith } 8009566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(pmat,prefix)); 80190f1c854SHong Zhang if (!wasSetup && pc->setfromoptionscalled) { 802248bfaf0SJed Brown /* If PCSetFromOptions_BJacobi is called later, KSPSetFromOptions will be called at that time. */ 8039566063dSJacob Faibussowitsch PetscCall(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) { 8179566063dSJacob Faibussowitsch PetscCall(MatDestroyMatrices(jac->n_local,&bjac->pmat)); 81849517cdeSBarry Smith if (pc->useAmat) { 8199566063dSJacob Faibussowitsch PetscCall(MatDestroyMatrices(jac->n_local,&bjac->mat)); 8204b9ad928SBarry Smith } 821e91c6855SBarry Smith } 8224b9ad928SBarry Smith 8234b9ad928SBarry Smith for (i=0; i<jac->n_local; i++) { 8249566063dSJacob Faibussowitsch PetscCall(KSPReset(jac->ksp[i])); 825e91c6855SBarry Smith if (bjac && bjac->x) { 8269566063dSJacob Faibussowitsch PetscCall(VecDestroy(&bjac->x[i])); 8279566063dSJacob Faibussowitsch PetscCall(VecDestroy(&bjac->y[i])); 8289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&bjac->is[i])); 8294b9ad928SBarry Smith } 830e91c6855SBarry Smith } 8319566063dSJacob Faibussowitsch PetscCall(PetscFree(jac->l_lens)); 8329566063dSJacob Faibussowitsch PetscCall(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; 8439566063dSJacob Faibussowitsch PetscCall(PCReset_BJacobi_Multiblock(pc)); 844c2efdce3SBarry Smith if (bjac) { 8459566063dSJacob Faibussowitsch PetscCall(PetscFree2(bjac->x,bjac->y)); 8469566063dSJacob Faibussowitsch PetscCall(PetscFree(bjac->starts)); 8479566063dSJacob Faibussowitsch PetscCall(PetscFree(bjac->is)); 848c2efdce3SBarry Smith } 8499566063dSJacob Faibussowitsch PetscCall(PetscFree(jac->data)); 850e91c6855SBarry Smith for (i=0; i<jac->n_local; i++) { 8519566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&jac->ksp[i])); 852e91c6855SBarry Smith } 8539566063dSJacob Faibussowitsch PetscCall(PetscFree(jac->ksp)); 8549566063dSJacob Faibussowitsch PetscCall(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++) { 8669566063dSJacob Faibussowitsch PetscCall(KSPSetUp(jac->ksp[i])); 8679566063dSJacob Faibussowitsch PetscCall(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; 8879566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x,&xin)); 8889566063dSJacob Faibussowitsch PetscCall(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 */ 8959566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(bjac->x[i],xin+bjac->starts[i])); 8969566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(bjac->y[i],yin+bjac->starts[i])); 8974b9ad928SBarry Smith 8989566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_ApplyOnBlocks,jac->ksp[i],bjac->x[i],bjac->y[i],0)); 8999566063dSJacob Faibussowitsch PetscCall(KSPSolve(jac->ksp[i],bjac->x[i],bjac->y[i])); 9009566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(jac->ksp[i],pc,bjac->y[i])); 9019566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_ApplyOnBlocks,jac->ksp[i],bjac->x[i],bjac->y[i],0)); 902d11f3a42SBarry Smith 9039566063dSJacob Faibussowitsch PetscCall(VecResetArray(bjac->x[i])); 9049566063dSJacob Faibussowitsch PetscCall(VecResetArray(bjac->y[i])); 9054b9ad928SBarry Smith } 9069566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x,&xin)); 9079566063dSJacob Faibussowitsch PetscCall(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; 9239566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x,&xin)); 9249566063dSJacob Faibussowitsch PetscCall(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 */ 9319566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(bjac->x[i],xin+bjac->starts[i])); 9329566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(bjac->y[i],yin+bjac->starts[i])); 9334b9ad928SBarry Smith 9349566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_ApplyTransposeOnBlocks,jac->ksp[i],bjac->x[i],bjac->y[i],0)); 9359566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(jac->ksp[i],bjac->x[i],bjac->y[i])); 9369566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(jac->ksp[i],pc,bjac->y[i])); 9379566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_ApplyTransposeOnBlocks,jac->ksp[i],bjac->x[i],bjac->y[i],0)); 938a7ff49e8SJed Brown 9399566063dSJacob Faibussowitsch PetscCall(VecResetArray(bjac->x[i])); 9409566063dSJacob Faibussowitsch PetscCall(VecResetArray(bjac->y[i])); 9414b9ad928SBarry Smith } 9429566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x,&xin)); 9439566063dSJacob Faibussowitsch PetscCall(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; 9619566063dSJacob Faibussowitsch PetscCall(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; 9679566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)mat,((PetscObject)pmat)->type_name,&same)); 96828b400f6SJacob 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 9829566063dSJacob Faibussowitsch PetscCall(PetscNewLog(pc,&bjac)); 9839566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_local,&jac->ksp)); 9849566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)pc,sizeof(n_local*sizeof(KSP)))); 9859566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(n_local,&bjac->x,n_local,&bjac->y)); 9869566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_local,&bjac->starts)); 9879566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)pc,sizeof(n_local*sizeof(PetscScalar)))); 9884b9ad928SBarry Smith 9894b9ad928SBarry Smith jac->data = (void*)bjac; 9909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_local,&bjac->is)); 9919566063dSJacob Faibussowitsch PetscCall(PetscLogObjectMemory((PetscObject)pc,sizeof(n_local*sizeof(IS)))); 9924b9ad928SBarry Smith 9934b9ad928SBarry Smith for (i=0; i<n_local; i++) { 9949566063dSJacob Faibussowitsch PetscCall(KSPCreate(PETSC_COMM_SELF,&ksp)); 9959566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(ksp,pc->erroriffailure)); 9969566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,1)); 9979566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)pc,(PetscObject)ksp)); 9989566063dSJacob Faibussowitsch PetscCall(KSPSetType(ksp,KSPPREONLY)); 9999566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp,&subpc)); 10009566063dSJacob Faibussowitsch PetscCall(PCGetOptionsPrefix(pc,&prefix)); 10019566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(ksp,prefix)); 10029566063dSJacob Faibussowitsch PetscCall(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; 10119566063dSJacob Faibussowitsch PetscCall(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 */ 10229566063dSJacob Faibussowitsch PetscCall(VecCreateSeq(PETSC_COMM_SELF,m,&x)); 10239566063dSJacob Faibussowitsch PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF,1,m,NULL,&y)); 10249566063dSJacob Faibussowitsch PetscCall(VecSetType(x,vectype)); 10259566063dSJacob Faibussowitsch PetscCall(VecSetType(y,vectype)); 10269566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)pc,(PetscObject)x)); 10279566063dSJacob Faibussowitsch PetscCall(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 10339566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF,m,start,1,&is)); 10344b9ad928SBarry Smith bjac->is[i] = is; 10359566063dSJacob Faibussowitsch PetscCall(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) { 10459566063dSJacob Faibussowitsch PetscCall(MatDestroyMatrices(n_local,&bjac->pmat)); 104649517cdeSBarry Smith if (pc->useAmat) { 10479566063dSJacob Faibussowitsch PetscCall(MatDestroyMatrices(n_local,&bjac->mat)); 10484b9ad928SBarry Smith } 10494b9ad928SBarry Smith scall = MAT_INITIAL_MATRIX; 10502fa5cd67SKarl Rupp } else scall = MAT_REUSE_MATRIX; 10514b9ad928SBarry Smith } 10524b9ad928SBarry Smith 10539566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(pmat,n_local,bjac->is,bjac->is,scall,&bjac->pmat)); 105449517cdeSBarry Smith if (pc->useAmat) { 10559566063dSJacob Faibussowitsch PetscCall(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) */ 10599566063dSJacob Faibussowitsch PetscCall(PCModifySubMatrices(pc,n_local,bjac->is,bjac->is,bjac->pmat,pc->modifysubmatricesP)); 10604b9ad928SBarry Smith 10614b9ad928SBarry Smith for (i=0; i<n_local; i++) { 10629566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)pc,(PetscObject)bjac->pmat[i])); 10639566063dSJacob Faibussowitsch PetscCall(KSPGetOptionsPrefix(jac->ksp[i],&prefix)); 106449517cdeSBarry Smith if (pc->useAmat) { 10659566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)pc,(PetscObject)bjac->mat[i])); 10669566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(jac->ksp[i],bjac->mat[i],bjac->pmat[i])); 10679566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(bjac->mat[i],prefix)); 10684b9ad928SBarry Smith } else { 10699566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(jac->ksp[i],bjac->pmat[i],bjac->pmat[i])); 10704b9ad928SBarry Smith } 10719566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(bjac->pmat[i],prefix)); 107290f1c854SHong Zhang if (pc->setfromoptionscalled) { 10739566063dSJacob Faibussowitsch PetscCall(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; 10909566063dSJacob Faibussowitsch PetscCall(KSPSetUp(subksp)); 10919566063dSJacob Faibussowitsch PetscCall(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; 11049566063dSJacob Faibussowitsch PetscCall(VecDestroy(&mpjac->ysub)); 11059566063dSJacob Faibussowitsch PetscCall(VecDestroy(&mpjac->xsub)); 11069566063dSJacob Faibussowitsch PetscCall(MatDestroy(&mpjac->submats)); 11079566063dSJacob Faibussowitsch if (jac->ksp) PetscCall(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; 11179566063dSJacob Faibussowitsch PetscCall(PCReset_BJacobi_Multiproc(pc)); 11189566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&jac->ksp[0])); 11199566063dSJacob Faibussowitsch PetscCall(PetscFree(jac->ksp)); 11209566063dSJacob Faibussowitsch PetscCall(PetscSubcommDestroy(&mpjac->psubcomm)); 11215a7e1895SHong Zhang 11229566063dSJacob Faibussowitsch PetscCall(PetscFree(mpjac)); 11239566063dSJacob Faibussowitsch PetscCall(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 */ 11379566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x,&xarray)); 11389566063dSJacob Faibussowitsch PetscCall(VecGetArray(y,&yarray)); 11399566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(mpjac->xsub,xarray)); 11409566063dSJacob Faibussowitsch PetscCall(VecPlaceArray(mpjac->ysub,yarray)); 11415a7e1895SHong Zhang 11425a7e1895SHong Zhang /* apply preconditioner on each matrix block */ 11439566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_ApplyOnBlocks,jac->ksp[0],mpjac->xsub,mpjac->ysub,0)); 11449566063dSJacob Faibussowitsch PetscCall(KSPSolve(jac->ksp[0],mpjac->xsub,mpjac->ysub)); 11459566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(jac->ksp[0],pc,mpjac->ysub)); 11469566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_ApplyOnBlocks,jac->ksp[0],mpjac->xsub,mpjac->ysub,0)); 11479566063dSJacob Faibussowitsch PetscCall(KSPGetConvergedReason(jac->ksp[0],&reason)); 1148c0decd05SBarry Smith if (reason == KSP_DIVERGED_PC_FAILED) { 1149261222b2SHong Zhang pc->failedreason = PC_SUBPC_ERROR; 1150250cf88bSHong Zhang } 1151250cf88bSHong Zhang 11529566063dSJacob Faibussowitsch PetscCall(VecResetArray(mpjac->xsub)); 11539566063dSJacob Faibussowitsch PetscCall(VecResetArray(mpjac->ysub)); 11549566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x,&xarray)); 11559566063dSJacob Faibussowitsch PetscCall(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 */ 11709566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(X,&m,NULL)); 11719566063dSJacob Faibussowitsch PetscCall(MatGetSize(X,NULL,&N)); 11729566063dSJacob Faibussowitsch PetscCall(MatDenseGetLDA(X,&lda)); 11739566063dSJacob Faibussowitsch PetscCall(MatDenseGetLDA(Y,&ldb)); 11749566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(X,&x)); 11759566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayWrite(Y,&y)); 11769566063dSJacob Faibussowitsch PetscCall(MatCreateDense(PetscObjectComm((PetscObject)jac->ksp[0]),m,PETSC_DECIDE,PETSC_DECIDE,N,(PetscScalar*)x,&sX)); 11779566063dSJacob Faibussowitsch PetscCall(MatCreateDense(PetscObjectComm((PetscObject)jac->ksp[0]),m,PETSC_DECIDE,PETSC_DECIDE,N,y,&sY)); 11789566063dSJacob Faibussowitsch PetscCall(MatDenseSetLDA(sX,lda)); 11799566063dSJacob Faibussowitsch PetscCall(MatDenseSetLDA(sY,ldb)); 11809566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_ApplyOnBlocks,jac->ksp[0],X,Y,0)); 11819566063dSJacob Faibussowitsch PetscCall(KSPMatSolve(jac->ksp[0],sX,sY)); 11829566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(jac->ksp[0],pc,NULL)); 11839566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_ApplyOnBlocks,jac->ksp[0],X,Y,0)); 11849566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sY)); 11859566063dSJacob Faibussowitsch PetscCall(MatDestroy(&sX)); 11869566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayWrite(Y,&y)); 11879566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(X,&x)); 11889566063dSJacob Faibussowitsch PetscCall(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; 12069566063dSJacob Faibussowitsch PetscCall(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; 12119566063dSJacob Faibussowitsch PetscCall(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 */ 12179566063dSJacob Faibussowitsch PetscCall(PetscSubcommCreate(comm,&jac->psubcomm)); 12189566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetNumber(jac->psubcomm,jac->n)); 12199566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetType(jac->psubcomm,PETSC_SUBCOMM_CONTIGUOUS)); 12209566063dSJacob Faibussowitsch PetscCall(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 */ 12269566063dSJacob Faibussowitsch PetscCall(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 */ 12299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1,&jac->ksp)); 12309566063dSJacob Faibussowitsch PetscCall(KSPCreate(subcomm,&jac->ksp[0])); 12319566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(jac->ksp[0],pc->erroriffailure)); 12329566063dSJacob Faibussowitsch PetscCall(PetscObjectIncrementTabLevel((PetscObject)jac->ksp[0],(PetscObject)pc,1)); 12339566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->ksp[0])); 12349566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(jac->ksp[0],mpjac->submats,mpjac->submats)); 12359566063dSJacob Faibussowitsch PetscCall(KSPGetPC(jac->ksp[0],&mpjac->pc)); 12365a7e1895SHong Zhang 12379566063dSJacob Faibussowitsch PetscCall(PCGetOptionsPrefix(pc,&prefix)); 12389566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(jac->ksp[0],prefix)); 12399566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(jac->ksp[0],"sub_")); 12409566063dSJacob Faibussowitsch PetscCall(KSPGetOptionsPrefix(jac->ksp[0],&prefix)); 12419566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(mpjac->submats,prefix)); 12425a7e1895SHong Zhang 12435a7e1895SHong Zhang /* create dummy vectors xsub and ysub */ 12449566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mpjac->submats,&m,&n)); 12459566063dSJacob Faibussowitsch PetscCall(VecCreateMPIWithArray(subcomm,1,n,PETSC_DECIDE,NULL,&mpjac->xsub)); 12469566063dSJacob Faibussowitsch PetscCall(VecCreateMPIWithArray(subcomm,1,m,PETSC_DECIDE,NULL,&mpjac->ysub)); 12479566063dSJacob Faibussowitsch PetscCall(MatGetVecType(mpjac->submats,&vectype)); 12489566063dSJacob Faibussowitsch PetscCall(VecSetType(mpjac->xsub,vectype)); 12499566063dSJacob Faibussowitsch PetscCall(VecSetType(mpjac->ysub,vectype)); 12509566063dSJacob Faibussowitsch PetscCall(PetscLogObjectParent((PetscObject)pc,(PetscObject)mpjac->xsub)); 12519566063dSJacob Faibussowitsch PetscCall(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 */ 12629566063dSJacob Faibussowitsch if (mpjac->submats) PetscCall(MatDestroy(&mpjac->submats)); 12639566063dSJacob Faibussowitsch PetscCall(MatGetMultiProcBlock(pc->pmat,subcomm,MAT_INITIAL_MATRIX,&mpjac->submats)); 1264fc08c53fSHong Zhang } else { 12659566063dSJacob Faibussowitsch PetscCall(MatGetMultiProcBlock(pc->pmat,subcomm,MAT_REUSE_MATRIX,&mpjac->submats)); 12665a7e1895SHong Zhang } 12679566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(jac->ksp[0],mpjac->submats,mpjac->submats)); 12685a7e1895SHong Zhang } 12695a7e1895SHong Zhang 1270de0953f6SBarry Smith if (!wasSetup && pc->setfromoptionscalled) { 12719566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(jac->ksp[0])); 12725a7e1895SHong Zhang } 12735a7e1895SHong Zhang PetscFunctionReturn(0); 12745a7e1895SHong Zhang } 1275