1 2 /* 3 Defines a block Jacobi preconditioner. 4 */ 5 6 #include <../src/ksp/pc/impls/bjacobi/bjacobi.h> /*I "petscpc.h" I*/ 7 8 static PetscErrorCode PCSetUp_BJacobi_Singleblock(PC,Mat,Mat); 9 static PetscErrorCode PCSetUp_BJacobi_Multiblock(PC,Mat,Mat); 10 static PetscErrorCode PCSetUp_BJacobi_Multiproc(PC); 11 12 #undef __FUNCT__ 13 #define __FUNCT__ "PCSetUp_BJacobi" 14 static PetscErrorCode PCSetUp_BJacobi(PC pc) 15 { 16 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 17 Mat mat = pc->mat,pmat = pc->pmat; 18 PetscErrorCode ierr,(*f)(Mat,Mat*); 19 PetscInt N,M,start,i,sum,end; 20 PetscInt bs,i_start=-1,i_end=-1; 21 PetscMPIInt rank,size; 22 const char *pprefix,*mprefix; 23 24 PetscFunctionBegin; 25 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr); 26 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr); 27 ierr = MatGetLocalSize(pc->pmat,&M,&N);CHKERRQ(ierr); 28 ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr); 29 30 if (jac->n > 0 && jac->n < size) { 31 ierr = PCSetUp_BJacobi_Multiproc(pc);CHKERRQ(ierr); 32 PetscFunctionReturn(0); 33 } 34 35 /* -------------------------------------------------------------------------- 36 Determines the number of blocks assigned to each processor 37 -----------------------------------------------------------------------------*/ 38 39 /* local block count given */ 40 if (jac->n_local > 0 && jac->n < 0) { 41 ierr = MPIU_Allreduce(&jac->n_local,&jac->n,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr); 42 if (jac->l_lens) { /* check that user set these correctly */ 43 sum = 0; 44 for (i=0; i<jac->n_local; i++) { 45 if (jac->l_lens[i]/bs*bs !=jac->l_lens[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat blocksize doesn't match block Jacobi layout"); 46 sum += jac->l_lens[i]; 47 } 48 if (sum != M) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local lens set incorrectly"); 49 } else { 50 ierr = PetscMalloc1(jac->n_local,&jac->l_lens);CHKERRQ(ierr); 51 for (i=0; i<jac->n_local; i++) jac->l_lens[i] = bs*((M/bs)/jac->n_local + (((M/bs) % jac->n_local) > i)); 52 } 53 } else if (jac->n > 0 && jac->n_local < 0) { /* global block count given */ 54 /* global blocks given: determine which ones are local */ 55 if (jac->g_lens) { 56 /* check if the g_lens is has valid entries */ 57 for (i=0; i<jac->n; i++) { 58 if (!jac->g_lens[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Zero block not allowed"); 59 if (jac->g_lens[i]/bs*bs != jac->g_lens[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat blocksize doesn't match block Jacobi layout"); 60 } 61 if (size == 1) { 62 jac->n_local = jac->n; 63 ierr = PetscMalloc1(jac->n_local,&jac->l_lens);CHKERRQ(ierr); 64 ierr = PetscMemcpy(jac->l_lens,jac->g_lens,jac->n_local*sizeof(PetscInt));CHKERRQ(ierr); 65 /* check that user set these correctly */ 66 sum = 0; 67 for (i=0; i<jac->n_local; i++) sum += jac->l_lens[i]; 68 if (sum != M) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Global lens set incorrectly"); 69 } else { 70 ierr = MatGetOwnershipRange(pc->pmat,&start,&end);CHKERRQ(ierr); 71 /* loop over blocks determing first one owned by me */ 72 sum = 0; 73 for (i=0; i<jac->n+1; i++) { 74 if (sum == start) { i_start = i; goto start_1;} 75 if (i < jac->n) sum += jac->g_lens[i]; 76 } 77 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Block sizes used in PCBJacobiSetTotalBlocks()\nare not compatible with parallel matrix layout"); 78 start_1: 79 for (i=i_start; i<jac->n+1; i++) { 80 if (sum == end) { i_end = i; goto end_1; } 81 if (i < jac->n) sum += jac->g_lens[i]; 82 } 83 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Block sizes used in PCBJacobiSetTotalBlocks()\nare not compatible with parallel matrix layout"); 84 end_1: 85 jac->n_local = i_end - i_start; 86 ierr = PetscMalloc1(jac->n_local,&jac->l_lens);CHKERRQ(ierr); 87 ierr = PetscMemcpy(jac->l_lens,jac->g_lens+i_start,jac->n_local*sizeof(PetscInt));CHKERRQ(ierr); 88 } 89 } else { /* no global blocks given, determine then using default layout */ 90 jac->n_local = jac->n/size + ((jac->n % size) > rank); 91 ierr = PetscMalloc1(jac->n_local,&jac->l_lens);CHKERRQ(ierr); 92 for (i=0; i<jac->n_local; i++) { 93 jac->l_lens[i] = ((M/bs)/jac->n_local + (((M/bs) % jac->n_local) > i))*bs; 94 if (!jac->l_lens[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Too many blocks given"); 95 } 96 } 97 } else if (jac->n < 0 && jac->n_local < 0) { /* no blocks given */ 98 jac->n = size; 99 jac->n_local = 1; 100 ierr = PetscMalloc1(1,&jac->l_lens);CHKERRQ(ierr); 101 jac->l_lens[0] = M; 102 } else { /* jac->n > 0 && jac->n_local > 0 */ 103 if (!jac->l_lens) { 104 ierr = PetscMalloc1(jac->n_local,&jac->l_lens);CHKERRQ(ierr); 105 for (i=0; i<jac->n_local; i++) jac->l_lens[i] = bs*((M/bs)/jac->n_local + (((M/bs) % jac->n_local) > i)); 106 } 107 } 108 if (jac->n_local < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of blocks is less than number of processors"); 109 110 /* ------------------------- 111 Determines mat and pmat 112 ---------------------------*/ 113 ierr = PetscObjectQueryFunction((PetscObject)pc->mat,"MatGetDiagonalBlock_C",&f);CHKERRQ(ierr); 114 if (!f && size == 1) { 115 mat = pc->mat; 116 pmat = pc->pmat; 117 } else { 118 if (pc->useAmat) { 119 /* use block from Amat matrix, not Pmat for local MatMult() */ 120 ierr = MatGetDiagonalBlock(pc->mat,&mat);CHKERRQ(ierr); 121 /* make submatrix have same prefix as entire matrix */ 122 ierr = PetscObjectGetOptionsPrefix((PetscObject)pc->mat,&mprefix);CHKERRQ(ierr); 123 ierr = PetscObjectSetOptionsPrefix((PetscObject)mat,mprefix);CHKERRQ(ierr); 124 } 125 if (pc->pmat != pc->mat || !pc->useAmat) { 126 ierr = MatGetDiagonalBlock(pc->pmat,&pmat);CHKERRQ(ierr); 127 /* make submatrix have same prefix as entire matrix */ 128 ierr = PetscObjectGetOptionsPrefix((PetscObject)pc->pmat,&pprefix);CHKERRQ(ierr); 129 ierr = PetscObjectSetOptionsPrefix((PetscObject)pmat,pprefix);CHKERRQ(ierr); 130 } else pmat = mat; 131 } 132 133 /* ------ 134 Setup code depends on the number of blocks 135 */ 136 if (jac->n_local == 1) { 137 ierr = PCSetUp_BJacobi_Singleblock(pc,mat,pmat);CHKERRQ(ierr); 138 } else { 139 ierr = PCSetUp_BJacobi_Multiblock(pc,mat,pmat);CHKERRQ(ierr); 140 } 141 PetscFunctionReturn(0); 142 } 143 144 /* Default destroy, if it has never been setup */ 145 #undef __FUNCT__ 146 #define __FUNCT__ "PCDestroy_BJacobi" 147 static PetscErrorCode PCDestroy_BJacobi(PC pc) 148 { 149 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 150 PetscErrorCode ierr; 151 152 PetscFunctionBegin; 153 ierr = PetscFree(jac->g_lens);CHKERRQ(ierr); 154 ierr = PetscFree(jac->l_lens);CHKERRQ(ierr); 155 ierr = PetscFree(pc->data);CHKERRQ(ierr); 156 PetscFunctionReturn(0); 157 } 158 159 #undef __FUNCT__ 160 #define __FUNCT__ "PCSetFromOptions_BJacobi" 161 162 static PetscErrorCode PCSetFromOptions_BJacobi(PetscOptionItems *PetscOptionsObject,PC pc) 163 { 164 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 165 PetscErrorCode ierr; 166 PetscInt blocks,i; 167 PetscBool flg; 168 169 PetscFunctionBegin; 170 ierr = PetscOptionsHead(PetscOptionsObject,"Block Jacobi options");CHKERRQ(ierr); 171 ierr = PetscOptionsInt("-pc_bjacobi_blocks","Total number of blocks","PCBJacobiSetTotalBlocks",jac->n,&blocks,&flg);CHKERRQ(ierr); 172 if (flg) { 173 ierr = PCBJacobiSetTotalBlocks(pc,blocks,NULL);CHKERRQ(ierr); 174 } 175 if (jac->ksp) { 176 /* The sub-KSP has already been set up (e.g., PCSetUp_BJacobi_Singleblock), but KSPSetFromOptions was not called 177 * unless we had already been called. */ 178 for (i=0; i<jac->n_local; i++) { 179 ierr = KSPSetFromOptions(jac->ksp[i]);CHKERRQ(ierr); 180 } 181 } 182 ierr = PetscOptionsTail();CHKERRQ(ierr); 183 PetscFunctionReturn(0); 184 } 185 186 #include <petscdraw.h> 187 #undef __FUNCT__ 188 #define __FUNCT__ "PCView_BJacobi" 189 static PetscErrorCode PCView_BJacobi(PC pc,PetscViewer viewer) 190 { 191 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 192 PC_BJacobi_Multiproc *mpjac = (PC_BJacobi_Multiproc*)jac->data; 193 PetscErrorCode ierr; 194 PetscMPIInt rank; 195 PetscInt i; 196 PetscBool iascii,isstring,isdraw; 197 PetscViewer sviewer; 198 199 PetscFunctionBegin; 200 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 201 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr); 202 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 203 if (iascii) { 204 if (pc->useAmat) { 205 ierr = PetscViewerASCIIPrintf(viewer," block Jacobi: using Amat local matrix, number of blocks = %D\n",jac->n);CHKERRQ(ierr); 206 } 207 ierr = PetscViewerASCIIPrintf(viewer," block Jacobi: number of blocks = %D\n",jac->n);CHKERRQ(ierr); 208 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr); 209 if (jac->same_local_solves) { 210 ierr = PetscViewerASCIIPrintf(viewer," Local solve is same for all blocks, in the following KSP and PC objects:\n");CHKERRQ(ierr); 211 if (jac->ksp && !jac->psubcomm) { 212 ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 213 if (!rank) { 214 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 215 ierr = KSPView(jac->ksp[0],sviewer);CHKERRQ(ierr); 216 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 217 } 218 ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 219 } else if (mpjac && jac->ksp && mpjac->psubcomm) { 220 ierr = PetscViewerGetSubViewer(viewer,mpjac->psubcomm->child,&sviewer);CHKERRQ(ierr); 221 if (!mpjac->psubcomm->color) { 222 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 223 ierr = KSPView(*(jac->ksp),sviewer);CHKERRQ(ierr); 224 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 225 } 226 ierr = PetscViewerRestoreSubViewer(viewer,mpjac->psubcomm->child,&sviewer);CHKERRQ(ierr); 227 } 228 } else { 229 PetscInt n_global; 230 ierr = MPIU_Allreduce(&jac->n_local,&n_global,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr); 231 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 232 ierr = PetscViewerASCIIPrintf(viewer," Local solve info for each block is in the following KSP and PC objects:\n");CHKERRQ(ierr); 233 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] number of local blocks = %D, first local block number = %D\n", 234 rank,jac->n_local,jac->first_local);CHKERRQ(ierr); 235 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 236 ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 237 for (i=0; i<jac->n_local; i++) { 238 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] local block number %D\n",rank,i);CHKERRQ(ierr); 239 ierr = KSPView(jac->ksp[i],sviewer);CHKERRQ(ierr); 240 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"- - - - - - - - - - - - - - - - - -\n");CHKERRQ(ierr); 241 } 242 ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 243 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 244 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 245 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 246 } 247 } else if (isstring) { 248 ierr = PetscViewerStringSPrintf(viewer," blks=%D",jac->n);CHKERRQ(ierr); 249 ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 250 if (jac->ksp) {ierr = KSPView(jac->ksp[0],sviewer);CHKERRQ(ierr);} 251 ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 252 } else if (isdraw) { 253 PetscDraw draw; 254 char str[25]; 255 PetscReal x,y,bottom,h; 256 257 ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 258 ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr); 259 ierr = PetscSNPrintf(str,25,"Number blocks %D",jac->n);CHKERRQ(ierr); 260 ierr = PetscDrawStringBoxed(draw,x,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr); 261 bottom = y - h; 262 ierr = PetscDrawPushCurrentPoint(draw,x,bottom);CHKERRQ(ierr); 263 /* warning the communicator on viewer is different then on ksp in parallel */ 264 if (jac->ksp) {ierr = KSPView(jac->ksp[0],viewer);CHKERRQ(ierr);} 265 ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 266 } 267 PetscFunctionReturn(0); 268 } 269 270 /* -------------------------------------------------------------------------------------*/ 271 272 #undef __FUNCT__ 273 #define __FUNCT__ "PCBJacobiGetSubKSP_BJacobi" 274 static PetscErrorCode PCBJacobiGetSubKSP_BJacobi(PC pc,PetscInt *n_local,PetscInt *first_local,KSP **ksp) 275 { 276 PC_BJacobi *jac = (PC_BJacobi*)pc->data;; 277 278 PetscFunctionBegin; 279 if (!pc->setupcalled) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must call KSPSetUp() or PCSetUp() first"); 280 281 if (n_local) *n_local = jac->n_local; 282 if (first_local) *first_local = jac->first_local; 283 *ksp = jac->ksp; 284 jac->same_local_solves = PETSC_FALSE; /* Assume that local solves are now different; 285 not necessarily true though! This flag is 286 used only for PCView_BJacobi() */ 287 PetscFunctionReturn(0); 288 } 289 290 #undef __FUNCT__ 291 #define __FUNCT__ "PCBJacobiSetTotalBlocks_BJacobi" 292 static PetscErrorCode PCBJacobiSetTotalBlocks_BJacobi(PC pc,PetscInt blocks,PetscInt *lens) 293 { 294 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 295 PetscErrorCode ierr; 296 297 PetscFunctionBegin; 298 if (pc->setupcalled > 0 && jac->n!=blocks) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ORDER,"Cannot alter number of blocks after PCSetUp()/KSPSetUp() has been called"); 299 jac->n = blocks; 300 if (!lens) jac->g_lens = 0; 301 else { 302 ierr = PetscMalloc1(blocks,&jac->g_lens);CHKERRQ(ierr); 303 ierr = PetscLogObjectMemory((PetscObject)pc,blocks*sizeof(PetscInt));CHKERRQ(ierr); 304 ierr = PetscMemcpy(jac->g_lens,lens,blocks*sizeof(PetscInt));CHKERRQ(ierr); 305 } 306 PetscFunctionReturn(0); 307 } 308 309 #undef __FUNCT__ 310 #define __FUNCT__ "PCBJacobiGetTotalBlocks_BJacobi" 311 static PetscErrorCode PCBJacobiGetTotalBlocks_BJacobi(PC pc, PetscInt *blocks, const PetscInt *lens[]) 312 { 313 PC_BJacobi *jac = (PC_BJacobi*) pc->data; 314 315 PetscFunctionBegin; 316 *blocks = jac->n; 317 if (lens) *lens = jac->g_lens; 318 PetscFunctionReturn(0); 319 } 320 321 #undef __FUNCT__ 322 #define __FUNCT__ "PCBJacobiSetLocalBlocks_BJacobi" 323 static PetscErrorCode PCBJacobiSetLocalBlocks_BJacobi(PC pc,PetscInt blocks,const PetscInt lens[]) 324 { 325 PC_BJacobi *jac; 326 PetscErrorCode ierr; 327 328 PetscFunctionBegin; 329 jac = (PC_BJacobi*)pc->data; 330 331 jac->n_local = blocks; 332 if (!lens) jac->l_lens = 0; 333 else { 334 ierr = PetscMalloc1(blocks,&jac->l_lens);CHKERRQ(ierr); 335 ierr = PetscLogObjectMemory((PetscObject)pc,blocks*sizeof(PetscInt));CHKERRQ(ierr); 336 ierr = PetscMemcpy(jac->l_lens,lens,blocks*sizeof(PetscInt));CHKERRQ(ierr); 337 } 338 PetscFunctionReturn(0); 339 } 340 341 #undef __FUNCT__ 342 #define __FUNCT__ "PCBJacobiGetLocalBlocks_BJacobi" 343 static PetscErrorCode PCBJacobiGetLocalBlocks_BJacobi(PC pc, PetscInt *blocks, const PetscInt *lens[]) 344 { 345 PC_BJacobi *jac = (PC_BJacobi*) pc->data; 346 347 PetscFunctionBegin; 348 *blocks = jac->n_local; 349 if (lens) *lens = jac->l_lens; 350 PetscFunctionReturn(0); 351 } 352 353 /* -------------------------------------------------------------------------------------*/ 354 355 #undef __FUNCT__ 356 #define __FUNCT__ "PCBJacobiGetSubKSP" 357 /*@C 358 PCBJacobiGetSubKSP - Gets the local KSP contexts for all blocks on 359 this processor. 360 361 Note Collective 362 363 Input Parameter: 364 . pc - the preconditioner context 365 366 Output Parameters: 367 + n_local - the number of blocks on this processor, or NULL 368 . first_local - the global number of the first block on this processor, or NULL 369 - ksp - the array of KSP contexts 370 371 Notes: 372 After PCBJacobiGetSubKSP() the array of KSP contexts is not to be freed. 373 374 Currently for some matrix implementations only 1 block per processor 375 is supported. 376 377 You must call KSPSetUp() or PCSetUp() before calling PCBJacobiGetSubKSP(). 378 379 Fortran Usage: You must pass in a KSP array that is large enough to contain all the local KSPs. 380 You can call PCBJacobiGetSubKSP(pc,nlocal,firstlocal,NULL_OBJECT,ierr) to determine how large the 381 KSP array must be. 382 383 Level: advanced 384 385 .keywords: block, Jacobi, get, sub, KSP, context 386 387 .seealso: PCBJacobiGetSubKSP() 388 @*/ 389 PetscErrorCode PCBJacobiGetSubKSP(PC pc,PetscInt *n_local,PetscInt *first_local,KSP *ksp[]) 390 { 391 PetscErrorCode ierr; 392 393 PetscFunctionBegin; 394 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 395 ierr = PetscUseMethod(pc,"PCBJacobiGetSubKSP_C",(PC,PetscInt*,PetscInt*,KSP **),(pc,n_local,first_local,ksp));CHKERRQ(ierr); 396 PetscFunctionReturn(0); 397 } 398 399 #undef __FUNCT__ 400 #define __FUNCT__ "PCBJacobiSetTotalBlocks" 401 /*@ 402 PCBJacobiSetTotalBlocks - Sets the global number of blocks for the block 403 Jacobi preconditioner. 404 405 Collective on PC 406 407 Input Parameters: 408 + pc - the preconditioner context 409 . blocks - the number of blocks 410 - lens - [optional] integer array containing the size of each block 411 412 Options Database Key: 413 . -pc_bjacobi_blocks <blocks> - Sets the number of global blocks 414 415 Notes: 416 Currently only a limited number of blocking configurations are supported. 417 All processors sharing the PC must call this routine with the same data. 418 419 Level: intermediate 420 421 .keywords: set, number, Jacobi, global, total, blocks 422 423 .seealso: PCSetUseAmat(), PCBJacobiSetLocalBlocks() 424 @*/ 425 PetscErrorCode PCBJacobiSetTotalBlocks(PC pc,PetscInt blocks,const PetscInt lens[]) 426 { 427 PetscErrorCode ierr; 428 429 PetscFunctionBegin; 430 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 431 if (blocks <= 0) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Must have positive blocks"); 432 ierr = PetscTryMethod(pc,"PCBJacobiSetTotalBlocks_C",(PC,PetscInt,const PetscInt[]),(pc,blocks,lens));CHKERRQ(ierr); 433 PetscFunctionReturn(0); 434 } 435 436 #undef __FUNCT__ 437 #define __FUNCT__ "PCBJacobiGetTotalBlocks" 438 /*@C 439 PCBJacobiGetTotalBlocks - Gets the global number of blocks for the block 440 Jacobi preconditioner. 441 442 Not Collective 443 444 Input Parameter: 445 . pc - the preconditioner context 446 447 Output parameters: 448 + blocks - the number of blocks 449 - lens - integer array containing the size of each block 450 451 Level: intermediate 452 453 .keywords: get, number, Jacobi, global, total, blocks 454 455 .seealso: PCSetUseAmat(), PCBJacobiGetLocalBlocks() 456 @*/ 457 PetscErrorCode PCBJacobiGetTotalBlocks(PC pc, PetscInt *blocks, const PetscInt *lens[]) 458 { 459 PetscErrorCode ierr; 460 461 PetscFunctionBegin; 462 PetscValidHeaderSpecific(pc, PC_CLASSID,1); 463 PetscValidIntPointer(blocks,2); 464 ierr = PetscUseMethod(pc,"PCBJacobiGetTotalBlocks_C",(PC,PetscInt*, const PetscInt *[]),(pc,blocks,lens));CHKERRQ(ierr); 465 PetscFunctionReturn(0); 466 } 467 468 #undef __FUNCT__ 469 #define __FUNCT__ "PCBJacobiSetLocalBlocks" 470 /*@ 471 PCBJacobiSetLocalBlocks - Sets the local number of blocks for the block 472 Jacobi preconditioner. 473 474 Not Collective 475 476 Input Parameters: 477 + pc - the preconditioner context 478 . blocks - the number of blocks 479 - lens - [optional] integer array containing size of each block 480 481 Note: 482 Currently only a limited number of blocking configurations are supported. 483 484 Level: intermediate 485 486 .keywords: PC, set, number, Jacobi, local, blocks 487 488 .seealso: PCSetUseAmat(), PCBJacobiSetTotalBlocks() 489 @*/ 490 PetscErrorCode PCBJacobiSetLocalBlocks(PC pc,PetscInt blocks,const PetscInt lens[]) 491 { 492 PetscErrorCode ierr; 493 494 PetscFunctionBegin; 495 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 496 if (blocks < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must have nonegative blocks"); 497 ierr = PetscTryMethod(pc,"PCBJacobiSetLocalBlocks_C",(PC,PetscInt,const PetscInt []),(pc,blocks,lens));CHKERRQ(ierr); 498 PetscFunctionReturn(0); 499 } 500 501 #undef __FUNCT__ 502 #define __FUNCT__ "PCBJacobiGetLocalBlocks" 503 /*@C 504 PCBJacobiGetLocalBlocks - Gets the local number of blocks for the block 505 Jacobi preconditioner. 506 507 Not Collective 508 509 Input Parameters: 510 + pc - the preconditioner context 511 . blocks - the number of blocks 512 - lens - [optional] integer array containing size of each block 513 514 Note: 515 Currently only a limited number of blocking configurations are supported. 516 517 Level: intermediate 518 519 .keywords: PC, get, number, Jacobi, local, blocks 520 521 .seealso: PCSetUseAmat(), PCBJacobiGetTotalBlocks() 522 @*/ 523 PetscErrorCode PCBJacobiGetLocalBlocks(PC pc, PetscInt *blocks, const PetscInt *lens[]) 524 { 525 PetscErrorCode ierr; 526 527 PetscFunctionBegin; 528 PetscValidHeaderSpecific(pc, PC_CLASSID,1); 529 PetscValidIntPointer(blocks,2); 530 ierr = PetscUseMethod(pc,"PCBJacobiGetLocalBlocks_C",(PC,PetscInt*, const PetscInt *[]),(pc,blocks,lens));CHKERRQ(ierr); 531 PetscFunctionReturn(0); 532 } 533 534 /* -----------------------------------------------------------------------------------*/ 535 536 /*MC 537 PCBJACOBI - Use block Jacobi preconditioning, each block is (approximately) solved with 538 its own KSP object. 539 540 Options Database Keys: 541 . -pc_use_amat - use Amat to apply block of operator in inner Krylov method 542 543 Notes: Each processor can have one or more blocks, but a block cannot be shared by more 544 than one processor. Defaults to one block per processor. 545 546 To set options on the solvers for each block append -sub_ to all the KSP, KSP, and PC 547 options database keys. For example, -sub_pc_type ilu -sub_pc_factor_levels 1 -sub_ksp_type preonly 548 549 To set the options on the solvers separate for each block call PCBJacobiGetSubKSP() 550 and set the options directly on the resulting KSP object (you can access its PC 551 KSPGetPC()) 552 553 For CUSP vectors it is recommended to use exactly one block per MPI process for best 554 performance. Different block partitioning may lead to additional data transfers 555 between host and GPU that lead to degraded performance. 556 557 Level: beginner 558 559 Concepts: block Jacobi 560 561 562 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 563 PCASM, PCSetUseAmat(), PCGetUseAmat(), PCBJacobiGetSubKSP(), PCBJacobiSetTotalBlocks(), 564 PCBJacobiSetLocalBlocks(), PCSetModifySubmatrices() 565 M*/ 566 567 #undef __FUNCT__ 568 #define __FUNCT__ "PCCreate_BJacobi" 569 PETSC_EXTERN PetscErrorCode PCCreate_BJacobi(PC pc) 570 { 571 PetscErrorCode ierr; 572 PetscMPIInt rank; 573 PC_BJacobi *jac; 574 575 PetscFunctionBegin; 576 ierr = PetscNewLog(pc,&jac);CHKERRQ(ierr); 577 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr); 578 579 pc->ops->apply = 0; 580 pc->ops->applytranspose = 0; 581 pc->ops->setup = PCSetUp_BJacobi; 582 pc->ops->destroy = PCDestroy_BJacobi; 583 pc->ops->setfromoptions = PCSetFromOptions_BJacobi; 584 pc->ops->view = PCView_BJacobi; 585 pc->ops->applyrichardson = 0; 586 587 pc->data = (void*)jac; 588 jac->n = -1; 589 jac->n_local = -1; 590 jac->first_local = rank; 591 jac->ksp = 0; 592 jac->same_local_solves = PETSC_TRUE; 593 jac->g_lens = 0; 594 jac->l_lens = 0; 595 jac->psubcomm = 0; 596 597 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBJacobiGetSubKSP_C",PCBJacobiGetSubKSP_BJacobi);CHKERRQ(ierr); 598 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBJacobiSetTotalBlocks_C",PCBJacobiSetTotalBlocks_BJacobi);CHKERRQ(ierr); 599 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBJacobiGetTotalBlocks_C",PCBJacobiGetTotalBlocks_BJacobi);CHKERRQ(ierr); 600 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBJacobiSetLocalBlocks_C",PCBJacobiSetLocalBlocks_BJacobi);CHKERRQ(ierr); 601 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBJacobiGetLocalBlocks_C",PCBJacobiGetLocalBlocks_BJacobi);CHKERRQ(ierr); 602 PetscFunctionReturn(0); 603 } 604 605 /* --------------------------------------------------------------------------------------------*/ 606 /* 607 These are for a single block per processor; works for AIJ, BAIJ; Seq and MPI 608 */ 609 #undef __FUNCT__ 610 #define __FUNCT__ "PCReset_BJacobi_Singleblock" 611 static PetscErrorCode PCReset_BJacobi_Singleblock(PC pc) 612 { 613 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 614 PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data; 615 PetscErrorCode ierr; 616 617 PetscFunctionBegin; 618 ierr = KSPReset(jac->ksp[0]);CHKERRQ(ierr); 619 ierr = VecDestroy(&bjac->x);CHKERRQ(ierr); 620 ierr = VecDestroy(&bjac->y);CHKERRQ(ierr); 621 PetscFunctionReturn(0); 622 } 623 624 #undef __FUNCT__ 625 #define __FUNCT__ "PCDestroy_BJacobi_Singleblock" 626 static PetscErrorCode PCDestroy_BJacobi_Singleblock(PC pc) 627 { 628 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 629 PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data; 630 PetscErrorCode ierr; 631 632 PetscFunctionBegin; 633 ierr = PCReset_BJacobi_Singleblock(pc);CHKERRQ(ierr); 634 ierr = KSPDestroy(&jac->ksp[0]);CHKERRQ(ierr); 635 ierr = PetscFree(jac->ksp);CHKERRQ(ierr); 636 ierr = PetscFree(jac->l_lens);CHKERRQ(ierr); 637 ierr = PetscFree(jac->g_lens);CHKERRQ(ierr); 638 ierr = PetscFree(bjac);CHKERRQ(ierr); 639 ierr = PetscFree(pc->data);CHKERRQ(ierr); 640 PetscFunctionReturn(0); 641 } 642 643 #undef __FUNCT__ 644 #define __FUNCT__ "PCSetUpOnBlocks_BJacobi_Singleblock" 645 static PetscErrorCode PCSetUpOnBlocks_BJacobi_Singleblock(PC pc) 646 { 647 PetscErrorCode ierr; 648 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 649 KSP subksp = jac->ksp[0]; 650 KSPConvergedReason reason; 651 652 PetscFunctionBegin; 653 ierr = KSPSetUp(subksp);CHKERRQ(ierr); 654 ierr = KSPGetConvergedReason(subksp,&reason);CHKERRQ(ierr); 655 if (reason == KSP_DIVERGED_PCSETUP_FAILED) { 656 pc->failedreason = PC_SUBPC_ERROR; 657 } 658 PetscFunctionReturn(0); 659 } 660 661 #undef __FUNCT__ 662 #define __FUNCT__ "PCApply_BJacobi_Singleblock" 663 static PetscErrorCode PCApply_BJacobi_Singleblock(PC pc,Vec x,Vec y) 664 { 665 PetscErrorCode ierr; 666 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 667 PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data; 668 669 PetscFunctionBegin; 670 ierr = VecGetLocalVectorRead(x, bjac->x);CHKERRQ(ierr); 671 ierr = VecGetLocalVector(y, bjac->y);CHKERRQ(ierr); 672 /* Since the inner KSP matrix may point directly to the diagonal block of an MPI matrix the inner 673 matrix may change even if the outter KSP/PC has not updated the preconditioner, this will trigger a rebuild 674 of the inner preconditioner automatically unless we pass down the outter preconditioners reuse flag.*/ 675 ierr = KSPSetReusePreconditioner(jac->ksp[0],pc->reusepreconditioner);CHKERRQ(ierr); 676 ierr = KSPSolve(jac->ksp[0],bjac->x,bjac->y);CHKERRQ(ierr); 677 ierr = VecRestoreLocalVectorRead(x, bjac->x);CHKERRQ(ierr); 678 ierr = VecRestoreLocalVector(y, bjac->y);CHKERRQ(ierr); 679 PetscFunctionReturn(0); 680 } 681 682 #undef __FUNCT__ 683 #define __FUNCT__ "PCApplySymmetricLeft_BJacobi_Singleblock" 684 static PetscErrorCode PCApplySymmetricLeft_BJacobi_Singleblock(PC pc,Vec x,Vec y) 685 { 686 PetscErrorCode ierr; 687 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 688 PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data; 689 PetscScalar *y_array; 690 const PetscScalar *x_array; 691 PC subpc; 692 693 PetscFunctionBegin; 694 /* 695 The VecPlaceArray() is to avoid having to copy the 696 y vector into the bjac->x vector. The reason for 697 the bjac->x vector is that we need a sequential vector 698 for the sequential solve. 699 */ 700 ierr = VecGetArrayRead(x,&x_array);CHKERRQ(ierr); 701 ierr = VecGetArray(y,&y_array);CHKERRQ(ierr); 702 ierr = VecPlaceArray(bjac->x,x_array);CHKERRQ(ierr); 703 ierr = VecPlaceArray(bjac->y,y_array);CHKERRQ(ierr); 704 /* apply the symmetric left portion of the inner PC operator */ 705 /* note this by-passes the inner KSP and its options completely */ 706 ierr = KSPGetPC(jac->ksp[0],&subpc);CHKERRQ(ierr); 707 ierr = PCApplySymmetricLeft(subpc,bjac->x,bjac->y);CHKERRQ(ierr); 708 ierr = VecResetArray(bjac->x);CHKERRQ(ierr); 709 ierr = VecResetArray(bjac->y);CHKERRQ(ierr); 710 ierr = VecRestoreArrayRead(x,&x_array);CHKERRQ(ierr); 711 ierr = VecRestoreArray(y,&y_array);CHKERRQ(ierr); 712 PetscFunctionReturn(0); 713 } 714 715 #undef __FUNCT__ 716 #define __FUNCT__ "PCApplySymmetricRight_BJacobi_Singleblock" 717 static PetscErrorCode PCApplySymmetricRight_BJacobi_Singleblock(PC pc,Vec x,Vec y) 718 { 719 PetscErrorCode ierr; 720 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 721 PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data; 722 PetscScalar *y_array; 723 const PetscScalar *x_array; 724 PC subpc; 725 726 PetscFunctionBegin; 727 /* 728 The VecPlaceArray() is to avoid having to copy the 729 y vector into the bjac->x vector. The reason for 730 the bjac->x vector is that we need a sequential vector 731 for the sequential solve. 732 */ 733 ierr = VecGetArrayRead(x,&x_array);CHKERRQ(ierr); 734 ierr = VecGetArray(y,&y_array);CHKERRQ(ierr); 735 ierr = VecPlaceArray(bjac->x,x_array);CHKERRQ(ierr); 736 ierr = VecPlaceArray(bjac->y,y_array);CHKERRQ(ierr); 737 738 /* apply the symmetric right portion of the inner PC operator */ 739 /* note this by-passes the inner KSP and its options completely */ 740 741 ierr = KSPGetPC(jac->ksp[0],&subpc);CHKERRQ(ierr); 742 ierr = PCApplySymmetricRight(subpc,bjac->x,bjac->y);CHKERRQ(ierr); 743 744 ierr = VecRestoreArrayRead(x,&x_array);CHKERRQ(ierr); 745 ierr = VecRestoreArray(y,&y_array);CHKERRQ(ierr); 746 PetscFunctionReturn(0); 747 } 748 749 #undef __FUNCT__ 750 #define __FUNCT__ "PCApplyTranspose_BJacobi_Singleblock" 751 static PetscErrorCode PCApplyTranspose_BJacobi_Singleblock(PC pc,Vec x,Vec y) 752 { 753 PetscErrorCode ierr; 754 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 755 PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data; 756 PetscScalar *y_array; 757 const PetscScalar *x_array; 758 759 PetscFunctionBegin; 760 /* 761 The VecPlaceArray() is to avoid having to copy the 762 y vector into the bjac->x vector. The reason for 763 the bjac->x vector is that we need a sequential vector 764 for the sequential solve. 765 */ 766 ierr = VecGetArrayRead(x,&x_array);CHKERRQ(ierr); 767 ierr = VecGetArray(y,&y_array);CHKERRQ(ierr); 768 ierr = VecPlaceArray(bjac->x,x_array);CHKERRQ(ierr); 769 ierr = VecPlaceArray(bjac->y,y_array);CHKERRQ(ierr); 770 ierr = KSPSolveTranspose(jac->ksp[0],bjac->x,bjac->y);CHKERRQ(ierr); 771 ierr = VecResetArray(bjac->x);CHKERRQ(ierr); 772 ierr = VecResetArray(bjac->y);CHKERRQ(ierr); 773 ierr = VecRestoreArrayRead(x,&x_array);CHKERRQ(ierr); 774 ierr = VecRestoreArray(y,&y_array);CHKERRQ(ierr); 775 PetscFunctionReturn(0); 776 } 777 778 #undef __FUNCT__ 779 #define __FUNCT__ "PCSetUp_BJacobi_Singleblock" 780 static PetscErrorCode PCSetUp_BJacobi_Singleblock(PC pc,Mat mat,Mat pmat) 781 { 782 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 783 PetscErrorCode ierr; 784 PetscInt m; 785 KSP ksp; 786 PC_BJacobi_Singleblock *bjac; 787 PetscBool wasSetup = PETSC_TRUE; 788 789 PetscFunctionBegin; 790 if (!pc->setupcalled) { 791 const char *prefix; 792 793 if (!jac->ksp) { 794 wasSetup = PETSC_FALSE; 795 796 ierr = KSPCreate(PETSC_COMM_SELF,&ksp);CHKERRQ(ierr); 797 ierr = KSPSetErrorIfNotConverged(ksp,pc->erroriffailure);CHKERRQ(ierr); 798 ierr = PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,1);CHKERRQ(ierr); 799 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)ksp);CHKERRQ(ierr); 800 ierr = KSPSetType(ksp,KSPPREONLY);CHKERRQ(ierr); 801 ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr); 802 ierr = KSPSetOptionsPrefix(ksp,prefix);CHKERRQ(ierr); 803 ierr = KSPAppendOptionsPrefix(ksp,"sub_");CHKERRQ(ierr); 804 805 pc->ops->reset = PCReset_BJacobi_Singleblock; 806 pc->ops->destroy = PCDestroy_BJacobi_Singleblock; 807 pc->ops->apply = PCApply_BJacobi_Singleblock; 808 pc->ops->applysymmetricleft = PCApplySymmetricLeft_BJacobi_Singleblock; 809 pc->ops->applysymmetricright = PCApplySymmetricRight_BJacobi_Singleblock; 810 pc->ops->applytranspose = PCApplyTranspose_BJacobi_Singleblock; 811 pc->ops->setuponblocks = PCSetUpOnBlocks_BJacobi_Singleblock; 812 813 ierr = PetscMalloc1(1,&jac->ksp);CHKERRQ(ierr); 814 jac->ksp[0] = ksp; 815 816 ierr = PetscNewLog(pc,&bjac);CHKERRQ(ierr); 817 jac->data = (void*)bjac; 818 } else { 819 ksp = jac->ksp[0]; 820 bjac = (PC_BJacobi_Singleblock*)jac->data; 821 } 822 823 /* 824 The reason we need to generate these vectors is to serve 825 as the right-hand side and solution vector for the solve on the 826 block. We do not need to allocate space for the vectors since 827 that is provided via VecPlaceArray() just before the call to 828 KSPSolve() on the block. 829 */ 830 ierr = MatGetSize(pmat,&m,&m);CHKERRQ(ierr); 831 ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,m,NULL,&bjac->x);CHKERRQ(ierr); 832 ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,m,NULL,&bjac->y);CHKERRQ(ierr); 833 #if defined(PETSC_HAVE_CUSP) 834 ierr = VecSetType(bjac->x,VECCUSP);CHKERRQ(ierr); 835 ierr = VecSetType(bjac->y,VECCUSP);CHKERRQ(ierr); 836 #elif defined(PETSC_HAVE_VECCUDA) 837 ierr = VecSetType(bjac->x,VECCUDA);CHKERRQ(ierr); 838 ierr = VecSetType(bjac->y,VECCUDA);CHKERRQ(ierr); 839 #endif 840 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)bjac->x);CHKERRQ(ierr); 841 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)bjac->y);CHKERRQ(ierr); 842 } else { 843 ksp = jac->ksp[0]; 844 bjac = (PC_BJacobi_Singleblock*)jac->data; 845 } 846 if (pc->useAmat) { 847 ierr = KSPSetOperators(ksp,mat,pmat);CHKERRQ(ierr); 848 } else { 849 ierr = KSPSetOperators(ksp,pmat,pmat);CHKERRQ(ierr); 850 } 851 if (!wasSetup && pc->setfromoptionscalled) { 852 /* If PCSetFromOptions_BJacobi is called later, KSPSetFromOptions will be called at that time. */ 853 ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); 854 } 855 PetscFunctionReturn(0); 856 } 857 858 /* ---------------------------------------------------------------------------------------------*/ 859 #undef __FUNCT__ 860 #define __FUNCT__ "PCReset_BJacobi_Multiblock" 861 static PetscErrorCode PCReset_BJacobi_Multiblock(PC pc) 862 { 863 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 864 PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data; 865 PetscErrorCode ierr; 866 PetscInt i; 867 868 PetscFunctionBegin; 869 if (bjac && bjac->pmat) { 870 ierr = MatDestroyMatrices(jac->n_local,&bjac->pmat);CHKERRQ(ierr); 871 if (pc->useAmat) { 872 ierr = MatDestroyMatrices(jac->n_local,&bjac->mat);CHKERRQ(ierr); 873 } 874 } 875 876 for (i=0; i<jac->n_local; i++) { 877 ierr = KSPReset(jac->ksp[i]);CHKERRQ(ierr); 878 if (bjac && bjac->x) { 879 ierr = VecDestroy(&bjac->x[i]);CHKERRQ(ierr); 880 ierr = VecDestroy(&bjac->y[i]);CHKERRQ(ierr); 881 ierr = ISDestroy(&bjac->is[i]);CHKERRQ(ierr); 882 } 883 } 884 ierr = PetscFree(jac->l_lens);CHKERRQ(ierr); 885 ierr = PetscFree(jac->g_lens);CHKERRQ(ierr); 886 PetscFunctionReturn(0); 887 } 888 889 #undef __FUNCT__ 890 #define __FUNCT__ "PCDestroy_BJacobi_Multiblock" 891 static PetscErrorCode PCDestroy_BJacobi_Multiblock(PC pc) 892 { 893 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 894 PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data; 895 PetscErrorCode ierr; 896 PetscInt i; 897 898 PetscFunctionBegin; 899 ierr = PCReset_BJacobi_Multiblock(pc);CHKERRQ(ierr); 900 if (bjac) { 901 ierr = PetscFree2(bjac->x,bjac->y);CHKERRQ(ierr); 902 ierr = PetscFree(bjac->starts);CHKERRQ(ierr); 903 ierr = PetscFree(bjac->is);CHKERRQ(ierr); 904 } 905 ierr = PetscFree(jac->data);CHKERRQ(ierr); 906 for (i=0; i<jac->n_local; i++) { 907 ierr = KSPDestroy(&jac->ksp[i]);CHKERRQ(ierr); 908 } 909 ierr = PetscFree(jac->ksp);CHKERRQ(ierr); 910 ierr = PetscFree(pc->data);CHKERRQ(ierr); 911 PetscFunctionReturn(0); 912 } 913 914 #undef __FUNCT__ 915 #define __FUNCT__ "PCSetUpOnBlocks_BJacobi_Multiblock" 916 static PetscErrorCode PCSetUpOnBlocks_BJacobi_Multiblock(PC pc) 917 { 918 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 919 PetscErrorCode ierr; 920 PetscInt i,n_local = jac->n_local; 921 KSPConvergedReason reason; 922 923 PetscFunctionBegin; 924 for (i=0; i<n_local; i++) { 925 ierr = KSPSetUp(jac->ksp[i]);CHKERRQ(ierr); 926 ierr = KSPGetConvergedReason(jac->ksp[i],&reason);CHKERRQ(ierr); 927 if (reason == KSP_DIVERGED_PCSETUP_FAILED) { 928 pc->failedreason = PC_SUBPC_ERROR; 929 } 930 } 931 PetscFunctionReturn(0); 932 } 933 934 /* 935 Preconditioner for block Jacobi 936 */ 937 #undef __FUNCT__ 938 #define __FUNCT__ "PCApply_BJacobi_Multiblock" 939 static PetscErrorCode PCApply_BJacobi_Multiblock(PC pc,Vec x,Vec y) 940 { 941 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 942 PetscErrorCode ierr; 943 PetscInt i,n_local = jac->n_local; 944 PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data; 945 PetscScalar *yin; 946 const PetscScalar *xin; 947 948 PetscFunctionBegin; 949 ierr = VecGetArrayRead(x,&xin);CHKERRQ(ierr); 950 ierr = VecGetArray(y,&yin);CHKERRQ(ierr); 951 for (i=0; i<n_local; i++) { 952 /* 953 To avoid copying the subvector from x into a workspace we instead 954 make the workspace vector array point to the subpart of the array of 955 the global vector. 956 */ 957 ierr = VecPlaceArray(bjac->x[i],xin+bjac->starts[i]);CHKERRQ(ierr); 958 ierr = VecPlaceArray(bjac->y[i],yin+bjac->starts[i]);CHKERRQ(ierr); 959 960 ierr = PetscLogEventBegin(PC_ApplyOnBlocks,jac->ksp[i],bjac->x[i],bjac->y[i],0);CHKERRQ(ierr); 961 ierr = KSPSolve(jac->ksp[i],bjac->x[i],bjac->y[i]);CHKERRQ(ierr); 962 ierr = PetscLogEventEnd(PC_ApplyOnBlocks,jac->ksp[i],bjac->x[i],bjac->y[i],0);CHKERRQ(ierr); 963 964 ierr = VecResetArray(bjac->x[i]);CHKERRQ(ierr); 965 ierr = VecResetArray(bjac->y[i]);CHKERRQ(ierr); 966 } 967 ierr = VecRestoreArrayRead(x,&xin);CHKERRQ(ierr); 968 ierr = VecRestoreArray(y,&yin);CHKERRQ(ierr); 969 PetscFunctionReturn(0); 970 } 971 972 /* 973 Preconditioner for block Jacobi 974 */ 975 #undef __FUNCT__ 976 #define __FUNCT__ "PCApplyTranspose_BJacobi_Multiblock" 977 static PetscErrorCode PCApplyTranspose_BJacobi_Multiblock(PC pc,Vec x,Vec y) 978 { 979 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 980 PetscErrorCode ierr; 981 PetscInt i,n_local = jac->n_local; 982 PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data; 983 PetscScalar *yin; 984 const PetscScalar *xin; 985 986 PetscFunctionBegin; 987 ierr = VecGetArrayRead(x,&xin);CHKERRQ(ierr); 988 ierr = VecGetArray(y,&yin);CHKERRQ(ierr); 989 for (i=0; i<n_local; i++) { 990 /* 991 To avoid copying the subvector from x into a workspace we instead 992 make the workspace vector array point to the subpart of the array of 993 the global vector. 994 */ 995 ierr = VecPlaceArray(bjac->x[i],xin+bjac->starts[i]);CHKERRQ(ierr); 996 ierr = VecPlaceArray(bjac->y[i],yin+bjac->starts[i]);CHKERRQ(ierr); 997 998 ierr = PetscLogEventBegin(PC_ApplyTransposeOnBlocks,jac->ksp[i],bjac->x[i],bjac->y[i],0);CHKERRQ(ierr); 999 ierr = KSPSolveTranspose(jac->ksp[i],bjac->x[i],bjac->y[i]);CHKERRQ(ierr); 1000 ierr = PetscLogEventEnd(PC_ApplyTransposeOnBlocks,jac->ksp[i],bjac->x[i],bjac->y[i],0);CHKERRQ(ierr); 1001 1002 ierr = VecResetArray(bjac->x[i]);CHKERRQ(ierr); 1003 ierr = VecResetArray(bjac->y[i]);CHKERRQ(ierr); 1004 } 1005 ierr = VecRestoreArrayRead(x,&xin);CHKERRQ(ierr); 1006 ierr = VecRestoreArray(y,&yin);CHKERRQ(ierr); 1007 PetscFunctionReturn(0); 1008 } 1009 1010 #undef __FUNCT__ 1011 #define __FUNCT__ "PCSetUp_BJacobi_Multiblock" 1012 static PetscErrorCode PCSetUp_BJacobi_Multiblock(PC pc,Mat mat,Mat pmat) 1013 { 1014 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 1015 PetscErrorCode ierr; 1016 PetscInt m,n_local,N,M,start,i; 1017 const char *prefix,*pprefix,*mprefix; 1018 KSP ksp; 1019 Vec x,y; 1020 PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data; 1021 PC subpc; 1022 IS is; 1023 MatReuse scall; 1024 1025 PetscFunctionBegin; 1026 ierr = MatGetLocalSize(pc->pmat,&M,&N);CHKERRQ(ierr); 1027 1028 n_local = jac->n_local; 1029 1030 if (pc->useAmat) { 1031 PetscBool same; 1032 ierr = PetscObjectTypeCompare((PetscObject)mat,((PetscObject)pmat)->type_name,&same);CHKERRQ(ierr); 1033 if (!same) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Matrices not of same type"); 1034 } 1035 1036 if (!pc->setupcalled) { 1037 scall = MAT_INITIAL_MATRIX; 1038 1039 if (!jac->ksp) { 1040 pc->ops->reset = PCReset_BJacobi_Multiblock; 1041 pc->ops->destroy = PCDestroy_BJacobi_Multiblock; 1042 pc->ops->apply = PCApply_BJacobi_Multiblock; 1043 pc->ops->applytranspose= PCApplyTranspose_BJacobi_Multiblock; 1044 pc->ops->setuponblocks = PCSetUpOnBlocks_BJacobi_Multiblock; 1045 1046 ierr = PetscNewLog(pc,&bjac);CHKERRQ(ierr); 1047 ierr = PetscMalloc1(n_local,&jac->ksp);CHKERRQ(ierr); 1048 ierr = PetscLogObjectMemory((PetscObject)pc,sizeof(n_local*sizeof(KSP)));CHKERRQ(ierr); 1049 ierr = PetscMalloc2(n_local,&bjac->x,n_local,&bjac->y);CHKERRQ(ierr); 1050 ierr = PetscMalloc1(n_local,&bjac->starts);CHKERRQ(ierr); 1051 ierr = PetscLogObjectMemory((PetscObject)pc,sizeof(n_local*sizeof(PetscScalar)));CHKERRQ(ierr); 1052 1053 jac->data = (void*)bjac; 1054 ierr = PetscMalloc1(n_local,&bjac->is);CHKERRQ(ierr); 1055 ierr = PetscLogObjectMemory((PetscObject)pc,sizeof(n_local*sizeof(IS)));CHKERRQ(ierr); 1056 1057 for (i=0; i<n_local; i++) { 1058 ierr = KSPCreate(PETSC_COMM_SELF,&ksp);CHKERRQ(ierr); 1059 ierr = KSPSetErrorIfNotConverged(ksp,pc->erroriffailure);CHKERRQ(ierr); 1060 ierr = PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,1);CHKERRQ(ierr); 1061 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)ksp);CHKERRQ(ierr); 1062 ierr = KSPSetType(ksp,KSPPREONLY);CHKERRQ(ierr); 1063 ierr = KSPGetPC(ksp,&subpc);CHKERRQ(ierr); 1064 ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr); 1065 ierr = KSPSetOptionsPrefix(ksp,prefix);CHKERRQ(ierr); 1066 ierr = KSPAppendOptionsPrefix(ksp,"sub_");CHKERRQ(ierr); 1067 1068 jac->ksp[i] = ksp; 1069 } 1070 } else { 1071 bjac = (PC_BJacobi_Multiblock*)jac->data; 1072 } 1073 1074 start = 0; 1075 for (i=0; i<n_local; i++) { 1076 m = jac->l_lens[i]; 1077 /* 1078 The reason we need to generate these vectors is to serve 1079 as the right-hand side and solution vector for the solve on the 1080 block. We do not need to allocate space for the vectors since 1081 that is provided via VecPlaceArray() just before the call to 1082 KSPSolve() on the block. 1083 1084 */ 1085 ierr = VecCreateSeq(PETSC_COMM_SELF,m,&x);CHKERRQ(ierr); 1086 ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,m,NULL,&y);CHKERRQ(ierr); 1087 #if defined(PETSC_HAVE_CUSP) 1088 ierr = VecSetType(x,VECCUSP);CHKERRQ(ierr); 1089 ierr = VecSetType(y,VECCUSP);CHKERRQ(ierr); 1090 #elif defined(PETSC_HAVE_VECCUDA) 1091 ierr = VecSetType(x,VECCUDA);CHKERRQ(ierr); 1092 ierr = VecSetType(y,VECCUDA);CHKERRQ(ierr); 1093 #endif 1094 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)x);CHKERRQ(ierr); 1095 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)y);CHKERRQ(ierr); 1096 1097 bjac->x[i] = x; 1098 bjac->y[i] = y; 1099 bjac->starts[i] = start; 1100 1101 ierr = ISCreateStride(PETSC_COMM_SELF,m,start,1,&is);CHKERRQ(ierr); 1102 bjac->is[i] = is; 1103 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)is);CHKERRQ(ierr); 1104 1105 start += m; 1106 } 1107 } else { 1108 bjac = (PC_BJacobi_Multiblock*)jac->data; 1109 /* 1110 Destroy the blocks from the previous iteration 1111 */ 1112 if (pc->flag == DIFFERENT_NONZERO_PATTERN) { 1113 ierr = MatDestroyMatrices(n_local,&bjac->pmat);CHKERRQ(ierr); 1114 if (pc->useAmat) { 1115 ierr = MatDestroyMatrices(n_local,&bjac->mat);CHKERRQ(ierr); 1116 } 1117 scall = MAT_INITIAL_MATRIX; 1118 } else scall = MAT_REUSE_MATRIX; 1119 } 1120 1121 ierr = MatGetSubMatrices(pmat,n_local,bjac->is,bjac->is,scall,&bjac->pmat);CHKERRQ(ierr); 1122 if (pc->useAmat) { 1123 ierr = PetscObjectGetOptionsPrefix((PetscObject)mat,&mprefix);CHKERRQ(ierr); 1124 ierr = MatGetSubMatrices(mat,n_local,bjac->is,bjac->is,scall,&bjac->mat);CHKERRQ(ierr); 1125 } 1126 /* Return control to the user so that the submatrices can be modified (e.g., to apply 1127 different boundary conditions for the submatrices than for the global problem) */ 1128 ierr = PCModifySubMatrices(pc,n_local,bjac->is,bjac->is,bjac->pmat,pc->modifysubmatricesP);CHKERRQ(ierr); 1129 1130 ierr = PetscObjectGetOptionsPrefix((PetscObject)pmat,&pprefix);CHKERRQ(ierr); 1131 for (i=0; i<n_local; i++) { 1132 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)bjac->pmat[i]);CHKERRQ(ierr); 1133 ierr = PetscObjectSetOptionsPrefix((PetscObject)bjac->pmat[i],pprefix);CHKERRQ(ierr); 1134 if (pc->useAmat) { 1135 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)bjac->mat[i]);CHKERRQ(ierr); 1136 ierr = PetscObjectSetOptionsPrefix((PetscObject)bjac->mat[i],mprefix);CHKERRQ(ierr); 1137 ierr = KSPSetOperators(jac->ksp[i],bjac->mat[i],bjac->pmat[i]);CHKERRQ(ierr); 1138 } else { 1139 ierr = KSPSetOperators(jac->ksp[i],bjac->pmat[i],bjac->pmat[i]);CHKERRQ(ierr); 1140 } 1141 if (pc->setfromoptionscalled) { 1142 ierr = KSPSetFromOptions(jac->ksp[i]);CHKERRQ(ierr); 1143 } 1144 } 1145 PetscFunctionReturn(0); 1146 } 1147 1148 /* ---------------------------------------------------------------------------------------------*/ 1149 /* 1150 These are for a single block with multiple processes; 1151 */ 1152 #undef __FUNCT__ 1153 #define __FUNCT__ "PCReset_BJacobi_Multiproc" 1154 static PetscErrorCode PCReset_BJacobi_Multiproc(PC pc) 1155 { 1156 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 1157 PC_BJacobi_Multiproc *mpjac = (PC_BJacobi_Multiproc*)jac->data; 1158 PetscErrorCode ierr; 1159 1160 PetscFunctionBegin; 1161 ierr = VecDestroy(&mpjac->ysub);CHKERRQ(ierr); 1162 ierr = VecDestroy(&mpjac->xsub);CHKERRQ(ierr); 1163 ierr = MatDestroy(&mpjac->submats);CHKERRQ(ierr); 1164 if (jac->ksp) {ierr = KSPReset(jac->ksp[0]);CHKERRQ(ierr);} 1165 PetscFunctionReturn(0); 1166 } 1167 1168 #undef __FUNCT__ 1169 #define __FUNCT__ "PCDestroy_BJacobi_Multiproc" 1170 static PetscErrorCode PCDestroy_BJacobi_Multiproc(PC pc) 1171 { 1172 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 1173 PC_BJacobi_Multiproc *mpjac = (PC_BJacobi_Multiproc*)jac->data; 1174 PetscErrorCode ierr; 1175 1176 PetscFunctionBegin; 1177 ierr = PCReset_BJacobi_Multiproc(pc);CHKERRQ(ierr); 1178 ierr = KSPDestroy(&jac->ksp[0]);CHKERRQ(ierr); 1179 ierr = PetscFree(jac->ksp);CHKERRQ(ierr); 1180 ierr = PetscSubcommDestroy(&mpjac->psubcomm);CHKERRQ(ierr); 1181 1182 ierr = PetscFree(mpjac);CHKERRQ(ierr); 1183 ierr = PetscFree(pc->data);CHKERRQ(ierr); 1184 PetscFunctionReturn(0); 1185 } 1186 1187 #undef __FUNCT__ 1188 #define __FUNCT__ "PCApply_BJacobi_Multiproc" 1189 static PetscErrorCode PCApply_BJacobi_Multiproc(PC pc,Vec x,Vec y) 1190 { 1191 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 1192 PC_BJacobi_Multiproc *mpjac = (PC_BJacobi_Multiproc*)jac->data; 1193 PetscErrorCode ierr; 1194 PetscScalar *yarray; 1195 const PetscScalar *xarray; 1196 KSPConvergedReason reason; 1197 1198 PetscFunctionBegin; 1199 /* place x's and y's local arrays into xsub and ysub */ 1200 ierr = VecGetArrayRead(x,&xarray);CHKERRQ(ierr); 1201 ierr = VecGetArray(y,&yarray);CHKERRQ(ierr); 1202 ierr = VecPlaceArray(mpjac->xsub,xarray);CHKERRQ(ierr); 1203 ierr = VecPlaceArray(mpjac->ysub,yarray);CHKERRQ(ierr); 1204 1205 /* apply preconditioner on each matrix block */ 1206 ierr = PetscLogEventBegin(PC_ApplyOnMproc,jac->ksp[0],mpjac->xsub,mpjac->ysub,0);CHKERRQ(ierr); 1207 ierr = KSPSolve(jac->ksp[0],mpjac->xsub,mpjac->ysub);CHKERRQ(ierr); 1208 ierr = PetscLogEventEnd(PC_ApplyOnMproc,jac->ksp[0],mpjac->xsub,mpjac->ysub,0);CHKERRQ(ierr); 1209 ierr = KSPGetConvergedReason(jac->ksp[0],&reason);CHKERRQ(ierr); 1210 if (reason == KSP_DIVERGED_PCSETUP_FAILED) { 1211 pc->failedreason = PC_SUBPC_ERROR; 1212 } 1213 1214 ierr = VecResetArray(mpjac->xsub);CHKERRQ(ierr); 1215 ierr = VecResetArray(mpjac->ysub);CHKERRQ(ierr); 1216 ierr = VecRestoreArrayRead(x,&xarray);CHKERRQ(ierr); 1217 ierr = VecRestoreArray(y,&yarray);CHKERRQ(ierr); 1218 PetscFunctionReturn(0); 1219 } 1220 1221 #undef __FUNCT__ 1222 #define __FUNCT__ "PCSetUp_BJacobi_Multiproc" 1223 static PetscErrorCode PCSetUp_BJacobi_Multiproc(PC pc) 1224 { 1225 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 1226 PC_BJacobi_Multiproc *mpjac = (PC_BJacobi_Multiproc*)jac->data; 1227 PetscErrorCode ierr; 1228 PetscInt m,n; 1229 MPI_Comm comm,subcomm=0; 1230 const char *prefix; 1231 PetscBool wasSetup = PETSC_TRUE; 1232 1233 PetscFunctionBegin; 1234 ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr); 1235 if (jac->n_local > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Only a single block in a subcommunicator is supported"); 1236 jac->n_local = 1; /* currently only a single block is supported for a subcommunicator */ 1237 if (!pc->setupcalled) { 1238 wasSetup = PETSC_FALSE; 1239 ierr = PetscNewLog(pc,&mpjac);CHKERRQ(ierr); 1240 jac->data = (void*)mpjac; 1241 1242 /* initialize datastructure mpjac */ 1243 if (!jac->psubcomm) { 1244 /* Create default contiguous subcommunicatiors if user does not provide them */ 1245 ierr = PetscSubcommCreate(comm,&jac->psubcomm);CHKERRQ(ierr); 1246 ierr = PetscSubcommSetNumber(jac->psubcomm,jac->n);CHKERRQ(ierr); 1247 ierr = PetscSubcommSetType(jac->psubcomm,PETSC_SUBCOMM_CONTIGUOUS);CHKERRQ(ierr); 1248 ierr = PetscLogObjectMemory((PetscObject)pc,sizeof(PetscSubcomm));CHKERRQ(ierr); 1249 } 1250 mpjac->psubcomm = jac->psubcomm; 1251 subcomm = PetscSubcommChild(mpjac->psubcomm); 1252 1253 /* Get matrix blocks of pmat */ 1254 ierr = MatGetMultiProcBlock(pc->pmat,subcomm,MAT_INITIAL_MATRIX,&mpjac->submats);CHKERRQ(ierr); 1255 1256 /* create a new PC that processors in each subcomm have copy of */ 1257 ierr = PetscMalloc1(1,&jac->ksp);CHKERRQ(ierr); 1258 ierr = KSPCreate(subcomm,&jac->ksp[0]);CHKERRQ(ierr); 1259 ierr = KSPSetErrorIfNotConverged(jac->ksp[0],pc->erroriffailure);CHKERRQ(ierr); 1260 ierr = PetscObjectIncrementTabLevel((PetscObject)jac->ksp[0],(PetscObject)pc,1);CHKERRQ(ierr); 1261 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->ksp[0]);CHKERRQ(ierr); 1262 ierr = KSPSetOperators(jac->ksp[0],mpjac->submats,mpjac->submats);CHKERRQ(ierr); 1263 ierr = KSPGetPC(jac->ksp[0],&mpjac->pc);CHKERRQ(ierr); 1264 1265 ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr); 1266 ierr = KSPSetOptionsPrefix(jac->ksp[0],prefix);CHKERRQ(ierr); 1267 ierr = KSPAppendOptionsPrefix(jac->ksp[0],"sub_");CHKERRQ(ierr); 1268 /* 1269 PetscMPIInt rank,subsize,subrank; 1270 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 1271 ierr = MPI_Comm_size(subcomm,&subsize);CHKERRQ(ierr); 1272 ierr = MPI_Comm_rank(subcomm,&subrank);CHKERRQ(ierr); 1273 1274 ierr = MatGetLocalSize(mpjac->submats,&m,NULL);CHKERRQ(ierr); 1275 ierr = MatGetSize(mpjac->submats,&n,NULL);CHKERRQ(ierr); 1276 ierr = PetscSynchronizedPrintf(comm,"[%d], sub-size %d,sub-rank %d\n",rank,subsize,subrank); 1277 ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr); 1278 */ 1279 1280 /* create dummy vectors xsub and ysub */ 1281 ierr = MatGetLocalSize(mpjac->submats,&m,&n);CHKERRQ(ierr); 1282 ierr = VecCreateMPIWithArray(subcomm,1,n,PETSC_DECIDE,NULL,&mpjac->xsub);CHKERRQ(ierr); 1283 ierr = VecCreateMPIWithArray(subcomm,1,m,PETSC_DECIDE,NULL,&mpjac->ysub);CHKERRQ(ierr); 1284 #if defined(PETSC_HAVE_CUSP) 1285 ierr = VecSetType(mpjac->xsub,VECMPICUSP);CHKERRQ(ierr); 1286 ierr = VecSetType(mpjac->ysub,VECMPICUSP);CHKERRQ(ierr); 1287 #elif defined(PETSC_HAVE_VECCUDA) 1288 ierr = VecSetType(mpjac->xsub,VECMPICUDA);CHKERRQ(ierr); 1289 ierr = VecSetType(mpjac->ysub,VECMPICUDA);CHKERRQ(ierr); 1290 #endif 1291 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)mpjac->xsub);CHKERRQ(ierr); 1292 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)mpjac->ysub);CHKERRQ(ierr); 1293 1294 pc->ops->reset = PCReset_BJacobi_Multiproc; 1295 pc->ops->destroy = PCDestroy_BJacobi_Multiproc; 1296 pc->ops->apply = PCApply_BJacobi_Multiproc; 1297 } else { /* pc->setupcalled */ 1298 subcomm = PetscSubcommChild(mpjac->psubcomm); 1299 if (pc->flag == DIFFERENT_NONZERO_PATTERN) { 1300 /* destroy old matrix blocks, then get new matrix blocks */ 1301 if (mpjac->submats) {ierr = MatDestroy(&mpjac->submats);CHKERRQ(ierr);} 1302 ierr = MatGetMultiProcBlock(pc->pmat,subcomm,MAT_INITIAL_MATRIX,&mpjac->submats);CHKERRQ(ierr); 1303 } else { 1304 ierr = MatGetMultiProcBlock(pc->pmat,subcomm,MAT_REUSE_MATRIX,&mpjac->submats);CHKERRQ(ierr); 1305 } 1306 ierr = KSPSetOperators(jac->ksp[0],mpjac->submats,mpjac->submats);CHKERRQ(ierr); 1307 } 1308 1309 if (!wasSetup && pc->setfromoptionscalled) { 1310 ierr = KSPSetFromOptions(jac->ksp[0]);CHKERRQ(ierr); 1311 } 1312 PetscFunctionReturn(0); 1313 } 1314