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