1 2 /* 3 Defines a block Jacobi preconditioner. 4 */ 5 #include <petsc/private/pcimpl.h> /*I "petscpc.h" I*/ 6 #include <../src/ksp/pc/impls/bjacobi/bjacobi.h> 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 = MPI_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(PetscOptions *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 = PetscViewerGetSingleton(viewer,&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 = PetscViewerRestoreSingleton(viewer,&sviewer);CHKERRQ(ierr); 219 } else if (jac->psubcomm && !jac->psubcomm->color) { 220 ierr = PetscViewerASCIIGetStdout(PetscSubcommChild(mpjac->psubcomm),&sviewer);CHKERRQ(ierr); 221 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 222 ierr = KSPView(*(jac->ksp),sviewer);CHKERRQ(ierr); 223 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 224 } 225 } else { 226 PetscInt n_global; 227 ierr = MPI_Allreduce(&jac->n_local,&n_global,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr); 228 ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr); 229 ierr = PetscViewerASCIIPrintf(viewer," Local solve info for each block is in the following KSP and PC objects:\n");CHKERRQ(ierr); 230 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] number of local blocks = %D, first local block number = %D\n", 231 rank,jac->n_local,jac->first_local);CHKERRQ(ierr); 232 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 233 ierr = PetscViewerGetSingleton(viewer,&sviewer);CHKERRQ(ierr); 234 for (i=0; i<jac->n_local; i++) { 235 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] local block number %D\n",rank,i);CHKERRQ(ierr); 236 ierr = KSPView(jac->ksp[i],sviewer);CHKERRQ(ierr); 237 ierr = PetscViewerASCIISynchronizedPrintf(viewer,"- - - - - - - - - - - - - - - - - -\n");CHKERRQ(ierr); 238 } 239 ierr = PetscViewerRestoreSingleton(viewer,&sviewer);CHKERRQ(ierr); 240 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 241 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 242 ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr); 243 } 244 } else if (isstring) { 245 ierr = PetscViewerStringSPrintf(viewer," blks=%D",jac->n);CHKERRQ(ierr); 246 ierr = PetscViewerGetSingleton(viewer,&sviewer);CHKERRQ(ierr); 247 if (jac->ksp) {ierr = KSPView(jac->ksp[0],sviewer);CHKERRQ(ierr);} 248 ierr = PetscViewerRestoreSingleton(viewer,&sviewer);CHKERRQ(ierr); 249 } else if (isdraw) { 250 PetscDraw draw; 251 char str[25]; 252 PetscReal x,y,bottom,h; 253 254 ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 255 ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr); 256 ierr = PetscSNPrintf(str,25,"Number blocks %D",jac->n);CHKERRQ(ierr); 257 ierr = PetscDrawStringBoxed(draw,x,y,PETSC_DRAW_RED,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr); 258 bottom = y - h; 259 ierr = PetscDrawPushCurrentPoint(draw,x,bottom);CHKERRQ(ierr); 260 /* warning the communicator on viewer is different then on ksp in parallel */ 261 if (jac->ksp) {ierr = KSPView(jac->ksp[0],viewer);CHKERRQ(ierr);} 262 ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 263 } 264 PetscFunctionReturn(0); 265 } 266 267 /* -------------------------------------------------------------------------------------*/ 268 269 #undef __FUNCT__ 270 #define __FUNCT__ "PCBJacobiGetSubKSP_BJacobi" 271 static PetscErrorCode PCBJacobiGetSubKSP_BJacobi(PC pc,PetscInt *n_local,PetscInt *first_local,KSP **ksp) 272 { 273 PC_BJacobi *jac = (PC_BJacobi*)pc->data;; 274 275 PetscFunctionBegin; 276 if (!pc->setupcalled) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must call KSPSetUp() or PCSetUp() first"); 277 278 if (n_local) *n_local = jac->n_local; 279 if (first_local) *first_local = jac->first_local; 280 *ksp = jac->ksp; 281 jac->same_local_solves = PETSC_FALSE; /* Assume that local solves are now different; 282 not necessarily true though! This flag is 283 used only for PCView_BJacobi() */ 284 PetscFunctionReturn(0); 285 } 286 287 #undef __FUNCT__ 288 #define __FUNCT__ "PCBJacobiSetTotalBlocks_BJacobi" 289 static PetscErrorCode PCBJacobiSetTotalBlocks_BJacobi(PC pc,PetscInt blocks,PetscInt *lens) 290 { 291 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 292 PetscErrorCode ierr; 293 294 PetscFunctionBegin; 295 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"); 296 jac->n = blocks; 297 if (!lens) jac->g_lens = 0; 298 else { 299 ierr = PetscMalloc1(blocks,&jac->g_lens);CHKERRQ(ierr); 300 ierr = PetscLogObjectMemory((PetscObject)pc,blocks*sizeof(PetscInt));CHKERRQ(ierr); 301 ierr = PetscMemcpy(jac->g_lens,lens,blocks*sizeof(PetscInt));CHKERRQ(ierr); 302 } 303 PetscFunctionReturn(0); 304 } 305 306 #undef __FUNCT__ 307 #define __FUNCT__ "PCBJacobiGetTotalBlocks_BJacobi" 308 static PetscErrorCode PCBJacobiGetTotalBlocks_BJacobi(PC pc, PetscInt *blocks, const PetscInt *lens[]) 309 { 310 PC_BJacobi *jac = (PC_BJacobi*) pc->data; 311 312 PetscFunctionBegin; 313 *blocks = jac->n; 314 if (lens) *lens = jac->g_lens; 315 PetscFunctionReturn(0); 316 } 317 318 #undef __FUNCT__ 319 #define __FUNCT__ "PCBJacobiSetLocalBlocks_BJacobi" 320 static PetscErrorCode PCBJacobiSetLocalBlocks_BJacobi(PC pc,PetscInt blocks,const PetscInt lens[]) 321 { 322 PC_BJacobi *jac; 323 PetscErrorCode ierr; 324 325 PetscFunctionBegin; 326 jac = (PC_BJacobi*)pc->data; 327 328 jac->n_local = blocks; 329 if (!lens) jac->l_lens = 0; 330 else { 331 ierr = PetscMalloc1(blocks,&jac->l_lens);CHKERRQ(ierr); 332 ierr = PetscLogObjectMemory((PetscObject)pc,blocks*sizeof(PetscInt));CHKERRQ(ierr); 333 ierr = PetscMemcpy(jac->l_lens,lens,blocks*sizeof(PetscInt));CHKERRQ(ierr); 334 } 335 PetscFunctionReturn(0); 336 } 337 338 #undef __FUNCT__ 339 #define __FUNCT__ "PCBJacobiGetLocalBlocks_BJacobi" 340 static PetscErrorCode PCBJacobiGetLocalBlocks_BJacobi(PC pc, PetscInt *blocks, const PetscInt *lens[]) 341 { 342 PC_BJacobi *jac = (PC_BJacobi*) pc->data; 343 344 PetscFunctionBegin; 345 *blocks = jac->n_local; 346 if (lens) *lens = jac->l_lens; 347 PetscFunctionReturn(0); 348 } 349 350 /* -------------------------------------------------------------------------------------*/ 351 352 #undef __FUNCT__ 353 #define __FUNCT__ "PCBJacobiGetSubKSP" 354 /*@C 355 PCBJacobiGetSubKSP - Gets the local KSP contexts for all blocks on 356 this processor. 357 358 Note Collective 359 360 Input Parameter: 361 . pc - the preconditioner context 362 363 Output Parameters: 364 + n_local - the number of blocks on this processor, or NULL 365 . first_local - the global number of the first block on this processor, or NULL 366 - ksp - the array of KSP contexts 367 368 Notes: 369 After PCBJacobiGetSubKSP() the array of KSP contexts is not to be freed. 370 371 Currently for some matrix implementations only 1 block per processor 372 is supported. 373 374 You must call KSPSetUp() or PCSetUp() before calling PCBJacobiGetSubKSP(). 375 376 Fortran Usage: You must pass in a KSP array that is large enough to contain all the local KSPs. 377 You can call PCBJacobiGetSubKSP(pc,nlocal,firstlocal,NULL_OBJECT,ierr) to determine how large the 378 KSP array must be. 379 380 Level: advanced 381 382 .keywords: block, Jacobi, get, sub, KSP, context 383 384 .seealso: PCBJacobiGetSubKSP() 385 @*/ 386 PetscErrorCode PCBJacobiGetSubKSP(PC pc,PetscInt *n_local,PetscInt *first_local,KSP *ksp[]) 387 { 388 PetscErrorCode ierr; 389 390 PetscFunctionBegin; 391 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 392 ierr = PetscUseMethod(pc,"PCBJacobiGetSubKSP_C",(PC,PetscInt*,PetscInt*,KSP **),(pc,n_local,first_local,ksp));CHKERRQ(ierr); 393 PetscFunctionReturn(0); 394 } 395 396 #undef __FUNCT__ 397 #define __FUNCT__ "PCBJacobiSetTotalBlocks" 398 /*@ 399 PCBJacobiSetTotalBlocks - Sets the global number of blocks for the block 400 Jacobi preconditioner. 401 402 Collective on PC 403 404 Input Parameters: 405 + pc - the preconditioner context 406 . blocks - the number of blocks 407 - lens - [optional] integer array containing the size of each block 408 409 Options Database Key: 410 . -pc_bjacobi_blocks <blocks> - Sets the number of global blocks 411 412 Notes: 413 Currently only a limited number of blocking configurations are supported. 414 All processors sharing the PC must call this routine with the same data. 415 416 Level: intermediate 417 418 .keywords: set, number, Jacobi, global, total, blocks 419 420 .seealso: PCSetUseAmat(), PCBJacobiSetLocalBlocks() 421 @*/ 422 PetscErrorCode PCBJacobiSetTotalBlocks(PC pc,PetscInt blocks,const PetscInt lens[]) 423 { 424 PetscErrorCode ierr; 425 426 PetscFunctionBegin; 427 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 428 if (blocks <= 0) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_OUTOFRANGE,"Must have positive blocks"); 429 ierr = PetscTryMethod(pc,"PCBJacobiSetTotalBlocks_C",(PC,PetscInt,const PetscInt[]),(pc,blocks,lens));CHKERRQ(ierr); 430 PetscFunctionReturn(0); 431 } 432 433 #undef __FUNCT__ 434 #define __FUNCT__ "PCBJacobiGetTotalBlocks" 435 /*@C 436 PCBJacobiGetTotalBlocks - Gets the global number of blocks for the block 437 Jacobi preconditioner. 438 439 Not Collective 440 441 Input Parameter: 442 . pc - the preconditioner context 443 444 Output parameters: 445 + blocks - the number of blocks 446 - lens - integer array containing the size of each block 447 448 Level: intermediate 449 450 .keywords: get, number, Jacobi, global, total, blocks 451 452 .seealso: PCSetUseAmat(), PCBJacobiGetLocalBlocks() 453 @*/ 454 PetscErrorCode PCBJacobiGetTotalBlocks(PC pc, PetscInt *blocks, const PetscInt *lens[]) 455 { 456 PetscErrorCode ierr; 457 458 PetscFunctionBegin; 459 PetscValidHeaderSpecific(pc, PC_CLASSID,1); 460 PetscValidIntPointer(blocks,2); 461 ierr = PetscUseMethod(pc,"PCBJacobiGetTotalBlocks_C",(PC,PetscInt*, const PetscInt *[]),(pc,blocks,lens));CHKERRQ(ierr); 462 PetscFunctionReturn(0); 463 } 464 465 #undef __FUNCT__ 466 #define __FUNCT__ "PCBJacobiSetLocalBlocks" 467 /*@ 468 PCBJacobiSetLocalBlocks - Sets the local number of blocks for the block 469 Jacobi preconditioner. 470 471 Not Collective 472 473 Input Parameters: 474 + pc - the preconditioner context 475 . blocks - the number of blocks 476 - lens - [optional] integer array containing size of each block 477 478 Note: 479 Currently only a limited number of blocking configurations are supported. 480 481 Level: intermediate 482 483 .keywords: PC, set, number, Jacobi, local, blocks 484 485 .seealso: PCSetUseAmat(), PCBJacobiSetTotalBlocks() 486 @*/ 487 PetscErrorCode PCBJacobiSetLocalBlocks(PC pc,PetscInt blocks,const PetscInt lens[]) 488 { 489 PetscErrorCode ierr; 490 491 PetscFunctionBegin; 492 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 493 if (blocks < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must have nonegative blocks"); 494 ierr = PetscTryMethod(pc,"PCBJacobiSetLocalBlocks_C",(PC,PetscInt,const PetscInt []),(pc,blocks,lens));CHKERRQ(ierr); 495 PetscFunctionReturn(0); 496 } 497 498 #undef __FUNCT__ 499 #define __FUNCT__ "PCBJacobiGetLocalBlocks" 500 /*@C 501 PCBJacobiGetLocalBlocks - Gets the local number of blocks for the block 502 Jacobi preconditioner. 503 504 Not Collective 505 506 Input Parameters: 507 + pc - the preconditioner context 508 . blocks - the number of blocks 509 - lens - [optional] integer array containing size of each block 510 511 Note: 512 Currently only a limited number of blocking configurations are supported. 513 514 Level: intermediate 515 516 .keywords: PC, get, number, Jacobi, local, blocks 517 518 .seealso: PCSetUseAmat(), PCBJacobiGetTotalBlocks() 519 @*/ 520 PetscErrorCode PCBJacobiGetLocalBlocks(PC pc, PetscInt *blocks, const PetscInt *lens[]) 521 { 522 PetscErrorCode ierr; 523 524 PetscFunctionBegin; 525 PetscValidHeaderSpecific(pc, PC_CLASSID,1); 526 PetscValidIntPointer(blocks,2); 527 ierr = PetscUseMethod(pc,"PCBJacobiGetLocalBlocks_C",(PC,PetscInt*, const PetscInt *[]),(pc,blocks,lens));CHKERRQ(ierr); 528 PetscFunctionReturn(0); 529 } 530 531 /* -----------------------------------------------------------------------------------*/ 532 533 /*MC 534 PCBJACOBI - Use block Jacobi preconditioning, each block is (approximately) solved with 535 its own KSP object. 536 537 Options Database Keys: 538 . -pc_use_amat - use Amat to apply block of operator in inner Krylov method 539 540 Notes: Each processor can have one or more blocks, but a block cannot be shared by more 541 than one processor. Defaults to one block per processor. 542 543 To set options on the solvers for each block append -sub_ to all the KSP, KSP, and PC 544 options database keys. For example, -sub_pc_type ilu -sub_pc_factor_levels 1 -sub_ksp_type preonly 545 546 To set the options on the solvers separate for each block call PCBJacobiGetSubKSP() 547 and set the options directly on the resulting KSP object (you can access its PC 548 KSPGetPC()) 549 550 Level: beginner 551 552 Concepts: block Jacobi 553 554 Developer Notes: This preconditioner does not currently work with CUDA/CUSP for a couple of reasons. 555 (1) It creates seq vectors as work vectors that should be cusp 556 (2) The use of VecPlaceArray() is not handled properly by CUSP (that is it will not know where 557 the ownership of the vector is so may use wrong values) even if it did know the ownership 558 it may induce extra copy ups and downs. Satish suggests a VecTransplantArray() to handle two 559 vectors sharing the same pointer and handling the CUSP side as well instead of VecGetArray()/VecPlaceArray(). 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 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 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 PetscErrorCode PCSetUpOnBlocks_BJacobi_Singleblock(PC pc) 646 { 647 PetscErrorCode ierr; 648 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 649 650 PetscFunctionBegin; 651 ierr = KSPSetUp(jac->ksp[0]);CHKERRQ(ierr); 652 PetscFunctionReturn(0); 653 } 654 655 #undef __FUNCT__ 656 #define __FUNCT__ "PCApply_BJacobi_Singleblock" 657 PetscErrorCode PCApply_BJacobi_Singleblock(PC pc,Vec x,Vec y) 658 { 659 PetscErrorCode ierr; 660 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 661 PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data; 662 663 PetscFunctionBegin; 664 ierr = VecGetLocalVectorRead(x, bjac->x);CHKERRQ(ierr); 665 ierr = VecGetLocalVector(y, bjac->y);CHKERRQ(ierr); 666 /* Since the inner KSP matrix may point directly to the diagonal block of an MPI matrix the inner 667 matrix may change even if the outter KSP/PC has not updated the preconditioner, this will trigger a rebuild 668 of the inner preconditioner automatically unless we pass down the outter preconditioners reuse flag.*/ 669 ierr = KSPSetReusePreconditioner(jac->ksp[0],pc->reusepreconditioner);CHKERRQ(ierr); 670 ierr = KSPSolve(jac->ksp[0],bjac->x,bjac->y);CHKERRQ(ierr); 671 ierr = VecRestoreLocalVectorRead(x, bjac->x);CHKERRQ(ierr); 672 ierr = VecRestoreLocalVector(y, bjac->y);CHKERRQ(ierr); 673 PetscFunctionReturn(0); 674 } 675 676 #undef __FUNCT__ 677 #define __FUNCT__ "PCApplySymmetricLeft_BJacobi_Singleblock" 678 PetscErrorCode PCApplySymmetricLeft_BJacobi_Singleblock(PC pc,Vec x,Vec y) 679 { 680 PetscErrorCode ierr; 681 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 682 PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data; 683 PetscScalar *y_array; 684 const PetscScalar *x_array; 685 PC subpc; 686 687 PetscFunctionBegin; 688 /* 689 The VecPlaceArray() is to avoid having to copy the 690 y vector into the bjac->x vector. The reason for 691 the bjac->x vector is that we need a sequential vector 692 for the sequential solve. 693 */ 694 ierr = VecGetArrayRead(x,&x_array);CHKERRQ(ierr); 695 ierr = VecGetArray(y,&y_array);CHKERRQ(ierr); 696 ierr = VecPlaceArray(bjac->x,x_array);CHKERRQ(ierr); 697 ierr = VecPlaceArray(bjac->y,y_array);CHKERRQ(ierr); 698 /* apply the symmetric left portion of the inner PC operator */ 699 /* note this by-passes the inner KSP and its options completely */ 700 ierr = KSPGetPC(jac->ksp[0],&subpc);CHKERRQ(ierr); 701 ierr = PCApplySymmetricLeft(subpc,bjac->x,bjac->y);CHKERRQ(ierr); 702 ierr = VecResetArray(bjac->x);CHKERRQ(ierr); 703 ierr = VecResetArray(bjac->y);CHKERRQ(ierr); 704 ierr = VecRestoreArrayRead(x,&x_array);CHKERRQ(ierr); 705 ierr = VecRestoreArray(y,&y_array);CHKERRQ(ierr); 706 PetscFunctionReturn(0); 707 } 708 709 #undef __FUNCT__ 710 #define __FUNCT__ "PCApplySymmetricRight_BJacobi_Singleblock" 711 PetscErrorCode PCApplySymmetricRight_BJacobi_Singleblock(PC pc,Vec x,Vec y) 712 { 713 PetscErrorCode ierr; 714 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 715 PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data; 716 PetscScalar *y_array; 717 const PetscScalar *x_array; 718 PC subpc; 719 720 PetscFunctionBegin; 721 /* 722 The VecPlaceArray() is to avoid having to copy the 723 y vector into the bjac->x vector. The reason for 724 the bjac->x vector is that we need a sequential vector 725 for the sequential solve. 726 */ 727 ierr = VecGetArrayRead(x,&x_array);CHKERRQ(ierr); 728 ierr = VecGetArray(y,&y_array);CHKERRQ(ierr); 729 ierr = VecPlaceArray(bjac->x,x_array);CHKERRQ(ierr); 730 ierr = VecPlaceArray(bjac->y,y_array);CHKERRQ(ierr); 731 732 /* apply the symmetric right portion of the inner PC operator */ 733 /* note this by-passes the inner KSP and its options completely */ 734 735 ierr = KSPGetPC(jac->ksp[0],&subpc);CHKERRQ(ierr); 736 ierr = PCApplySymmetricRight(subpc,bjac->x,bjac->y);CHKERRQ(ierr); 737 738 ierr = VecRestoreArrayRead(x,&x_array);CHKERRQ(ierr); 739 ierr = VecRestoreArray(y,&y_array);CHKERRQ(ierr); 740 PetscFunctionReturn(0); 741 } 742 743 #undef __FUNCT__ 744 #define __FUNCT__ "PCApplyTranspose_BJacobi_Singleblock" 745 PetscErrorCode PCApplyTranspose_BJacobi_Singleblock(PC pc,Vec x,Vec y) 746 { 747 PetscErrorCode ierr; 748 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 749 PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data; 750 PetscScalar *y_array; 751 const PetscScalar *x_array; 752 753 PetscFunctionBegin; 754 /* 755 The VecPlaceArray() is to avoid having to copy the 756 y vector into the bjac->x vector. The reason for 757 the bjac->x vector is that we need a sequential vector 758 for the sequential solve. 759 */ 760 ierr = VecGetArrayRead(x,&x_array);CHKERRQ(ierr); 761 ierr = VecGetArray(y,&y_array);CHKERRQ(ierr); 762 ierr = VecPlaceArray(bjac->x,x_array);CHKERRQ(ierr); 763 ierr = VecPlaceArray(bjac->y,y_array);CHKERRQ(ierr); 764 ierr = KSPSolveTranspose(jac->ksp[0],bjac->x,bjac->y);CHKERRQ(ierr); 765 ierr = VecResetArray(bjac->x);CHKERRQ(ierr); 766 ierr = VecResetArray(bjac->y);CHKERRQ(ierr); 767 ierr = VecRestoreArrayRead(x,&x_array);CHKERRQ(ierr); 768 ierr = VecRestoreArray(y,&y_array);CHKERRQ(ierr); 769 PetscFunctionReturn(0); 770 } 771 772 #undef __FUNCT__ 773 #define __FUNCT__ "PCSetUp_BJacobi_Singleblock" 774 static PetscErrorCode PCSetUp_BJacobi_Singleblock(PC pc,Mat mat,Mat pmat) 775 { 776 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 777 PetscErrorCode ierr; 778 PetscInt m; 779 KSP ksp; 780 PC_BJacobi_Singleblock *bjac; 781 PetscBool wasSetup = PETSC_TRUE; 782 783 PetscFunctionBegin; 784 if (!pc->setupcalled) { 785 const char *prefix; 786 787 if (!jac->ksp) { 788 wasSetup = PETSC_FALSE; 789 790 ierr = KSPCreate(PETSC_COMM_SELF,&ksp);CHKERRQ(ierr); 791 ierr = KSPSetErrorIfNotConverged(ksp,pc->erroriffailure);CHKERRQ(ierr); 792 ierr = PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,1);CHKERRQ(ierr); 793 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)ksp);CHKERRQ(ierr); 794 ierr = KSPSetType(ksp,KSPPREONLY);CHKERRQ(ierr); 795 ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr); 796 ierr = KSPSetOptionsPrefix(ksp,prefix);CHKERRQ(ierr); 797 ierr = KSPAppendOptionsPrefix(ksp,"sub_");CHKERRQ(ierr); 798 799 pc->ops->reset = PCReset_BJacobi_Singleblock; 800 pc->ops->destroy = PCDestroy_BJacobi_Singleblock; 801 pc->ops->apply = PCApply_BJacobi_Singleblock; 802 pc->ops->applysymmetricleft = PCApplySymmetricLeft_BJacobi_Singleblock; 803 pc->ops->applysymmetricright = PCApplySymmetricRight_BJacobi_Singleblock; 804 pc->ops->applytranspose = PCApplyTranspose_BJacobi_Singleblock; 805 pc->ops->setuponblocks = PCSetUpOnBlocks_BJacobi_Singleblock; 806 807 ierr = PetscMalloc1(1,&jac->ksp);CHKERRQ(ierr); 808 jac->ksp[0] = ksp; 809 810 ierr = PetscNewLog(pc,&bjac);CHKERRQ(ierr); 811 jac->data = (void*)bjac; 812 } else { 813 ksp = jac->ksp[0]; 814 bjac = (PC_BJacobi_Singleblock*)jac->data; 815 } 816 817 /* 818 The reason we need to generate these vectors is to serve 819 as the right-hand side and solution vector for the solve on the 820 block. We do not need to allocate space for the vectors since 821 that is provided via VecPlaceArray() just before the call to 822 KSPSolve() on the block. 823 */ 824 ierr = MatGetSize(pmat,&m,&m);CHKERRQ(ierr); 825 ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,m,NULL,&bjac->x);CHKERRQ(ierr); 826 ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,m,NULL,&bjac->y);CHKERRQ(ierr); 827 #ifdef PETSC_HAVE_CUSP 828 ierr = VecSetType(bjac->x,VECCUSP);CHKERRQ(ierr); 829 ierr = VecSetType(bjac->y,VECCUSP);CHKERRQ(ierr); 830 #endif 831 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)bjac->x);CHKERRQ(ierr); 832 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)bjac->y);CHKERRQ(ierr); 833 } else { 834 ksp = jac->ksp[0]; 835 bjac = (PC_BJacobi_Singleblock*)jac->data; 836 } 837 if (pc->useAmat) { 838 ierr = KSPSetOperators(ksp,mat,pmat);CHKERRQ(ierr); 839 } else { 840 ierr = KSPSetOperators(ksp,pmat,pmat);CHKERRQ(ierr); 841 } 842 if (!wasSetup && pc->setfromoptionscalled) { 843 /* If PCSetFromOptions_BJacobi is called later, KSPSetFromOptions will be called at that time. */ 844 ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); 845 } 846 PetscFunctionReturn(0); 847 } 848 849 /* ---------------------------------------------------------------------------------------------*/ 850 #undef __FUNCT__ 851 #define __FUNCT__ "PCReset_BJacobi_Multiblock" 852 PetscErrorCode PCReset_BJacobi_Multiblock(PC pc) 853 { 854 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 855 PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data; 856 PetscErrorCode ierr; 857 PetscInt i; 858 859 PetscFunctionBegin; 860 if (bjac && bjac->pmat) { 861 ierr = MatDestroyMatrices(jac->n_local,&bjac->pmat);CHKERRQ(ierr); 862 if (pc->useAmat) { 863 ierr = MatDestroyMatrices(jac->n_local,&bjac->mat);CHKERRQ(ierr); 864 } 865 } 866 867 for (i=0; i<jac->n_local; i++) { 868 ierr = KSPReset(jac->ksp[i]);CHKERRQ(ierr); 869 if (bjac && bjac->x) { 870 ierr = VecDestroy(&bjac->x[i]);CHKERRQ(ierr); 871 ierr = VecDestroy(&bjac->y[i]);CHKERRQ(ierr); 872 ierr = ISDestroy(&bjac->is[i]);CHKERRQ(ierr); 873 } 874 } 875 ierr = PetscFree(jac->l_lens);CHKERRQ(ierr); 876 ierr = PetscFree(jac->g_lens);CHKERRQ(ierr); 877 PetscFunctionReturn(0); 878 } 879 880 #undef __FUNCT__ 881 #define __FUNCT__ "PCDestroy_BJacobi_Multiblock" 882 PetscErrorCode PCDestroy_BJacobi_Multiblock(PC pc) 883 { 884 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 885 PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data; 886 PetscErrorCode ierr; 887 PetscInt i; 888 889 PetscFunctionBegin; 890 ierr = PCReset_BJacobi_Multiblock(pc);CHKERRQ(ierr); 891 if (bjac) { 892 ierr = PetscFree2(bjac->x,bjac->y);CHKERRQ(ierr); 893 ierr = PetscFree(bjac->starts);CHKERRQ(ierr); 894 ierr = PetscFree(bjac->is);CHKERRQ(ierr); 895 } 896 ierr = PetscFree(jac->data);CHKERRQ(ierr); 897 for (i=0; i<jac->n_local; i++) { 898 ierr = KSPDestroy(&jac->ksp[i]);CHKERRQ(ierr); 899 } 900 ierr = PetscFree(jac->ksp);CHKERRQ(ierr); 901 ierr = PetscFree(pc->data);CHKERRQ(ierr); 902 PetscFunctionReturn(0); 903 } 904 905 #undef __FUNCT__ 906 #define __FUNCT__ "PCSetUpOnBlocks_BJacobi_Multiblock" 907 PetscErrorCode PCSetUpOnBlocks_BJacobi_Multiblock(PC pc) 908 { 909 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 910 PetscErrorCode ierr; 911 PetscInt i,n_local = jac->n_local; 912 913 PetscFunctionBegin; 914 for (i=0; i<n_local; i++) { 915 ierr = KSPSetUp(jac->ksp[i]);CHKERRQ(ierr); 916 } 917 PetscFunctionReturn(0); 918 } 919 920 /* 921 Preconditioner for block Jacobi 922 */ 923 #undef __FUNCT__ 924 #define __FUNCT__ "PCApply_BJacobi_Multiblock" 925 PetscErrorCode PCApply_BJacobi_Multiblock(PC pc,Vec x,Vec y) 926 { 927 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 928 PetscErrorCode ierr; 929 PetscInt i,n_local = jac->n_local; 930 PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data; 931 PetscScalar *yin; 932 const PetscScalar *xin; 933 934 PetscFunctionBegin; 935 ierr = VecGetArrayRead(x,&xin);CHKERRQ(ierr); 936 ierr = VecGetArray(y,&yin);CHKERRQ(ierr); 937 for (i=0; i<n_local; i++) { 938 /* 939 To avoid copying the subvector from x into a workspace we instead 940 make the workspace vector array point to the subpart of the array of 941 the global vector. 942 */ 943 ierr = VecPlaceArray(bjac->x[i],xin+bjac->starts[i]);CHKERRQ(ierr); 944 ierr = VecPlaceArray(bjac->y[i],yin+bjac->starts[i]);CHKERRQ(ierr); 945 946 ierr = PetscLogEventBegin(PC_ApplyOnBlocks,jac->ksp[i],bjac->x[i],bjac->y[i],0);CHKERRQ(ierr); 947 ierr = KSPSolve(jac->ksp[i],bjac->x[i],bjac->y[i]);CHKERRQ(ierr); 948 ierr = PetscLogEventEnd(PC_ApplyOnBlocks,jac->ksp[i],bjac->x[i],bjac->y[i],0);CHKERRQ(ierr); 949 950 ierr = VecResetArray(bjac->x[i]);CHKERRQ(ierr); 951 ierr = VecResetArray(bjac->y[i]);CHKERRQ(ierr); 952 } 953 ierr = VecRestoreArrayRead(x,&xin);CHKERRQ(ierr); 954 ierr = VecRestoreArray(y,&yin);CHKERRQ(ierr); 955 PetscFunctionReturn(0); 956 } 957 958 /* 959 Preconditioner for block Jacobi 960 */ 961 #undef __FUNCT__ 962 #define __FUNCT__ "PCApplyTranspose_BJacobi_Multiblock" 963 PetscErrorCode PCApplyTranspose_BJacobi_Multiblock(PC pc,Vec x,Vec y) 964 { 965 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 966 PetscErrorCode ierr; 967 PetscInt i,n_local = jac->n_local; 968 PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data; 969 PetscScalar *yin; 970 const PetscScalar *xin; 971 972 PetscFunctionBegin; 973 ierr = VecGetArrayRead(x,&xin);CHKERRQ(ierr); 974 ierr = VecGetArray(y,&yin);CHKERRQ(ierr); 975 for (i=0; i<n_local; i++) { 976 /* 977 To avoid copying the subvector from x into a workspace we instead 978 make the workspace vector array point to the subpart of the array of 979 the global vector. 980 */ 981 ierr = VecPlaceArray(bjac->x[i],xin+bjac->starts[i]);CHKERRQ(ierr); 982 ierr = VecPlaceArray(bjac->y[i],yin+bjac->starts[i]);CHKERRQ(ierr); 983 984 ierr = PetscLogEventBegin(PC_ApplyTransposeOnBlocks,jac->ksp[i],bjac->x[i],bjac->y[i],0);CHKERRQ(ierr); 985 ierr = KSPSolveTranspose(jac->ksp[i],bjac->x[i],bjac->y[i]);CHKERRQ(ierr); 986 ierr = PetscLogEventEnd(PC_ApplyTransposeOnBlocks,jac->ksp[i],bjac->x[i],bjac->y[i],0);CHKERRQ(ierr); 987 988 ierr = VecResetArray(bjac->x[i]);CHKERRQ(ierr); 989 ierr = VecResetArray(bjac->y[i]);CHKERRQ(ierr); 990 } 991 ierr = VecRestoreArrayRead(x,&xin);CHKERRQ(ierr); 992 ierr = VecRestoreArray(y,&yin);CHKERRQ(ierr); 993 PetscFunctionReturn(0); 994 } 995 996 #undef __FUNCT__ 997 #define __FUNCT__ "PCSetUp_BJacobi_Multiblock" 998 static PetscErrorCode PCSetUp_BJacobi_Multiblock(PC pc,Mat mat,Mat pmat) 999 { 1000 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 1001 PetscErrorCode ierr; 1002 PetscInt m,n_local,N,M,start,i; 1003 const char *prefix,*pprefix,*mprefix; 1004 KSP ksp; 1005 Vec x,y; 1006 PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data; 1007 PC subpc; 1008 IS is; 1009 MatReuse scall; 1010 1011 PetscFunctionBegin; 1012 ierr = MatGetLocalSize(pc->pmat,&M,&N);CHKERRQ(ierr); 1013 1014 n_local = jac->n_local; 1015 1016 if (pc->useAmat) { 1017 PetscBool same; 1018 ierr = PetscObjectTypeCompare((PetscObject)mat,((PetscObject)pmat)->type_name,&same);CHKERRQ(ierr); 1019 if (!same) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_INCOMP,"Matrices not of same type"); 1020 } 1021 1022 if (!pc->setupcalled) { 1023 scall = MAT_INITIAL_MATRIX; 1024 1025 if (!jac->ksp) { 1026 pc->ops->reset = PCReset_BJacobi_Multiblock; 1027 pc->ops->destroy = PCDestroy_BJacobi_Multiblock; 1028 pc->ops->apply = PCApply_BJacobi_Multiblock; 1029 pc->ops->applytranspose= PCApplyTranspose_BJacobi_Multiblock; 1030 pc->ops->setuponblocks = PCSetUpOnBlocks_BJacobi_Multiblock; 1031 1032 ierr = PetscNewLog(pc,&bjac);CHKERRQ(ierr); 1033 ierr = PetscMalloc1(n_local,&jac->ksp);CHKERRQ(ierr); 1034 ierr = PetscLogObjectMemory((PetscObject)pc,sizeof(n_local*sizeof(KSP)));CHKERRQ(ierr); 1035 ierr = PetscMalloc2(n_local,&bjac->x,n_local,&bjac->y);CHKERRQ(ierr); 1036 ierr = PetscMalloc1(n_local,&bjac->starts);CHKERRQ(ierr); 1037 ierr = PetscLogObjectMemory((PetscObject)pc,sizeof(n_local*sizeof(PetscScalar)));CHKERRQ(ierr); 1038 1039 jac->data = (void*)bjac; 1040 ierr = PetscMalloc1(n_local,&bjac->is);CHKERRQ(ierr); 1041 ierr = PetscLogObjectMemory((PetscObject)pc,sizeof(n_local*sizeof(IS)));CHKERRQ(ierr); 1042 1043 for (i=0; i<n_local; i++) { 1044 ierr = KSPCreate(PETSC_COMM_SELF,&ksp);CHKERRQ(ierr); 1045 ierr = KSPSetErrorIfNotConverged(ksp,pc->erroriffailure);CHKERRQ(ierr); 1046 ierr = PetscObjectIncrementTabLevel((PetscObject)ksp,(PetscObject)pc,1);CHKERRQ(ierr); 1047 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)ksp);CHKERRQ(ierr); 1048 ierr = KSPSetType(ksp,KSPPREONLY);CHKERRQ(ierr); 1049 ierr = KSPGetPC(ksp,&subpc);CHKERRQ(ierr); 1050 ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr); 1051 ierr = KSPSetOptionsPrefix(ksp,prefix);CHKERRQ(ierr); 1052 ierr = KSPAppendOptionsPrefix(ksp,"sub_");CHKERRQ(ierr); 1053 1054 jac->ksp[i] = ksp; 1055 } 1056 } else { 1057 bjac = (PC_BJacobi_Multiblock*)jac->data; 1058 } 1059 1060 start = 0; 1061 for (i=0; i<n_local; i++) { 1062 m = jac->l_lens[i]; 1063 /* 1064 The reason we need to generate these vectors is to serve 1065 as the right-hand side and solution vector for the solve on the 1066 block. We do not need to allocate space for the vectors since 1067 that is provided via VecPlaceArray() just before the call to 1068 KSPSolve() on the block. 1069 1070 */ 1071 ierr = VecCreateSeq(PETSC_COMM_SELF,m,&x);CHKERRQ(ierr); 1072 ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,m,NULL,&y);CHKERRQ(ierr); 1073 #ifdef PETSC_HAVE_CUSP 1074 ierr = VecSetType(x,VECCUSP);CHKERRQ(ierr); 1075 ierr = VecSetType(y,VECCUSP);CHKERRQ(ierr); 1076 #endif 1077 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)x);CHKERRQ(ierr); 1078 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)y);CHKERRQ(ierr); 1079 1080 bjac->x[i] = x; 1081 bjac->y[i] = y; 1082 bjac->starts[i] = start; 1083 1084 ierr = ISCreateStride(PETSC_COMM_SELF,m,start,1,&is);CHKERRQ(ierr); 1085 bjac->is[i] = is; 1086 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)is);CHKERRQ(ierr); 1087 1088 start += m; 1089 } 1090 } else { 1091 bjac = (PC_BJacobi_Multiblock*)jac->data; 1092 /* 1093 Destroy the blocks from the previous iteration 1094 */ 1095 if (pc->flag == DIFFERENT_NONZERO_PATTERN) { 1096 ierr = MatDestroyMatrices(n_local,&bjac->pmat);CHKERRQ(ierr); 1097 if (pc->useAmat) { 1098 ierr = MatDestroyMatrices(n_local,&bjac->mat);CHKERRQ(ierr); 1099 } 1100 scall = MAT_INITIAL_MATRIX; 1101 } else scall = MAT_REUSE_MATRIX; 1102 } 1103 1104 ierr = MatGetSubMatrices(pmat,n_local,bjac->is,bjac->is,scall,&bjac->pmat);CHKERRQ(ierr); 1105 if (pc->useAmat) { 1106 ierr = PetscObjectGetOptionsPrefix((PetscObject)mat,&mprefix);CHKERRQ(ierr); 1107 ierr = MatGetSubMatrices(mat,n_local,bjac->is,bjac->is,scall,&bjac->mat);CHKERRQ(ierr); 1108 } 1109 /* Return control to the user so that the submatrices can be modified (e.g., to apply 1110 different boundary conditions for the submatrices than for the global problem) */ 1111 ierr = PCModifySubMatrices(pc,n_local,bjac->is,bjac->is,bjac->pmat,pc->modifysubmatricesP);CHKERRQ(ierr); 1112 1113 ierr = PetscObjectGetOptionsPrefix((PetscObject)pmat,&pprefix);CHKERRQ(ierr); 1114 for (i=0; i<n_local; i++) { 1115 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)bjac->pmat[i]);CHKERRQ(ierr); 1116 ierr = PetscObjectSetOptionsPrefix((PetscObject)bjac->pmat[i],pprefix);CHKERRQ(ierr); 1117 if (pc->useAmat) { 1118 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)bjac->mat[i]);CHKERRQ(ierr); 1119 ierr = PetscObjectSetOptionsPrefix((PetscObject)bjac->mat[i],mprefix);CHKERRQ(ierr); 1120 ierr = KSPSetOperators(jac->ksp[i],bjac->mat[i],bjac->pmat[i]);CHKERRQ(ierr); 1121 } else { 1122 ierr = KSPSetOperators(jac->ksp[i],bjac->pmat[i],bjac->pmat[i]);CHKERRQ(ierr); 1123 } 1124 if (pc->setfromoptionscalled) { 1125 ierr = KSPSetFromOptions(jac->ksp[i]);CHKERRQ(ierr); 1126 } 1127 } 1128 PetscFunctionReturn(0); 1129 } 1130 1131 /* ---------------------------------------------------------------------------------------------*/ 1132 /* 1133 These are for a single block with multiple processes; 1134 */ 1135 #undef __FUNCT__ 1136 #define __FUNCT__ "PCReset_BJacobi_Multiproc" 1137 static PetscErrorCode PCReset_BJacobi_Multiproc(PC pc) 1138 { 1139 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 1140 PC_BJacobi_Multiproc *mpjac = (PC_BJacobi_Multiproc*)jac->data; 1141 PetscErrorCode ierr; 1142 1143 PetscFunctionBegin; 1144 ierr = VecDestroy(&mpjac->ysub);CHKERRQ(ierr); 1145 ierr = VecDestroy(&mpjac->xsub);CHKERRQ(ierr); 1146 ierr = MatDestroy(&mpjac->submats);CHKERRQ(ierr); 1147 if (jac->ksp) {ierr = KSPReset(jac->ksp[0]);CHKERRQ(ierr);} 1148 PetscFunctionReturn(0); 1149 } 1150 1151 #undef __FUNCT__ 1152 #define __FUNCT__ "PCDestroy_BJacobi_Multiproc" 1153 static PetscErrorCode PCDestroy_BJacobi_Multiproc(PC pc) 1154 { 1155 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 1156 PC_BJacobi_Multiproc *mpjac = (PC_BJacobi_Multiproc*)jac->data; 1157 PetscErrorCode ierr; 1158 1159 PetscFunctionBegin; 1160 ierr = PCReset_BJacobi_Multiproc(pc);CHKERRQ(ierr); 1161 ierr = KSPDestroy(&jac->ksp[0]);CHKERRQ(ierr); 1162 ierr = PetscFree(jac->ksp);CHKERRQ(ierr); 1163 ierr = PetscSubcommDestroy(&mpjac->psubcomm);CHKERRQ(ierr); 1164 1165 ierr = PetscFree(mpjac);CHKERRQ(ierr); 1166 ierr = PetscFree(pc->data);CHKERRQ(ierr); 1167 PetscFunctionReturn(0); 1168 } 1169 1170 #undef __FUNCT__ 1171 #define __FUNCT__ "PCApply_BJacobi_Multiproc" 1172 static PetscErrorCode PCApply_BJacobi_Multiproc(PC pc,Vec x,Vec y) 1173 { 1174 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 1175 PC_BJacobi_Multiproc *mpjac = (PC_BJacobi_Multiproc*)jac->data; 1176 PetscErrorCode ierr; 1177 PetscScalar *yarray; 1178 const PetscScalar *xarray; 1179 1180 PetscFunctionBegin; 1181 /* place x's and y's local arrays into xsub and ysub */ 1182 ierr = VecGetArrayRead(x,&xarray);CHKERRQ(ierr); 1183 ierr = VecGetArray(y,&yarray);CHKERRQ(ierr); 1184 ierr = VecPlaceArray(mpjac->xsub,xarray);CHKERRQ(ierr); 1185 ierr = VecPlaceArray(mpjac->ysub,yarray);CHKERRQ(ierr); 1186 1187 /* apply preconditioner on each matrix block */ 1188 ierr = PetscLogEventBegin(PC_ApplyOnMproc,jac->ksp[0],mpjac->xsub,mpjac->ysub,0);CHKERRQ(ierr); 1189 ierr = KSPSolve(jac->ksp[0],mpjac->xsub,mpjac->ysub);CHKERRQ(ierr); 1190 ierr = PetscLogEventEnd(PC_ApplyOnMproc,jac->ksp[0],mpjac->xsub,mpjac->ysub,0);CHKERRQ(ierr); 1191 1192 ierr = VecResetArray(mpjac->xsub);CHKERRQ(ierr); 1193 ierr = VecResetArray(mpjac->ysub);CHKERRQ(ierr); 1194 ierr = VecRestoreArrayRead(x,&xarray);CHKERRQ(ierr); 1195 ierr = VecRestoreArray(y,&yarray);CHKERRQ(ierr); 1196 PetscFunctionReturn(0); 1197 } 1198 1199 #include <petsc/private/matimpl.h> 1200 #undef __FUNCT__ 1201 #define __FUNCT__ "PCSetUp_BJacobi_Multiproc" 1202 static PetscErrorCode PCSetUp_BJacobi_Multiproc(PC pc) 1203 { 1204 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 1205 PC_BJacobi_Multiproc *mpjac = (PC_BJacobi_Multiproc*)jac->data; 1206 PetscErrorCode ierr; 1207 PetscInt m,n; 1208 MPI_Comm comm,subcomm=0; 1209 const char *prefix; 1210 PetscBool wasSetup = PETSC_TRUE; 1211 1212 PetscFunctionBegin; 1213 ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr); 1214 if (jac->n_local > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Only a single block in a subcommunicator is supported"); 1215 jac->n_local = 1; /* currently only a single block is supported for a subcommunicator */ 1216 if (!pc->setupcalled) { 1217 wasSetup = PETSC_FALSE; 1218 ierr = PetscNewLog(pc,&mpjac);CHKERRQ(ierr); 1219 jac->data = (void*)mpjac; 1220 1221 /* initialize datastructure mpjac */ 1222 if (!jac->psubcomm) { 1223 /* Create default contiguous subcommunicatiors if user does not provide them */ 1224 ierr = PetscSubcommCreate(comm,&jac->psubcomm);CHKERRQ(ierr); 1225 ierr = PetscSubcommSetNumber(jac->psubcomm,jac->n);CHKERRQ(ierr); 1226 ierr = PetscSubcommSetType(jac->psubcomm,PETSC_SUBCOMM_CONTIGUOUS);CHKERRQ(ierr); 1227 ierr = PetscLogObjectMemory((PetscObject)pc,sizeof(PetscSubcomm));CHKERRQ(ierr); 1228 } 1229 mpjac->psubcomm = jac->psubcomm; 1230 subcomm = PetscSubcommChild(mpjac->psubcomm); 1231 1232 /* Get matrix blocks of pmat */ 1233 if (!pc->pmat->ops->getmultiprocblock) SETERRQ(PetscObjectComm((PetscObject)pc->pmat),PETSC_ERR_SUP,"No support for the requested operation"); 1234 ierr = (*pc->pmat->ops->getmultiprocblock)(pc->pmat,subcomm,MAT_INITIAL_MATRIX,&mpjac->submats);CHKERRQ(ierr); 1235 1236 /* create a new PC that processors in each subcomm have copy of */ 1237 ierr = PetscMalloc1(1,&jac->ksp);CHKERRQ(ierr); 1238 ierr = KSPCreate(subcomm,&jac->ksp[0]);CHKERRQ(ierr); 1239 ierr = KSPSetErrorIfNotConverged(jac->ksp[0],pc->erroriffailure);CHKERRQ(ierr); 1240 ierr = PetscObjectIncrementTabLevel((PetscObject)jac->ksp[0],(PetscObject)pc,1);CHKERRQ(ierr); 1241 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)jac->ksp[0]);CHKERRQ(ierr); 1242 ierr = KSPSetOperators(jac->ksp[0],mpjac->submats,mpjac->submats);CHKERRQ(ierr); 1243 ierr = KSPGetPC(jac->ksp[0],&mpjac->pc);CHKERRQ(ierr); 1244 1245 ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr); 1246 ierr = KSPSetOptionsPrefix(jac->ksp[0],prefix);CHKERRQ(ierr); 1247 ierr = KSPAppendOptionsPrefix(jac->ksp[0],"sub_");CHKERRQ(ierr); 1248 /* 1249 PetscMPIInt rank,subsize,subrank; 1250 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 1251 ierr = MPI_Comm_size(subcomm,&subsize);CHKERRQ(ierr); 1252 ierr = MPI_Comm_rank(subcomm,&subrank);CHKERRQ(ierr); 1253 1254 ierr = MatGetLocalSize(mpjac->submats,&m,NULL);CHKERRQ(ierr); 1255 ierr = MatGetSize(mpjac->submats,&n,NULL);CHKERRQ(ierr); 1256 ierr = PetscSynchronizedPrintf(comm,"[%d], sub-size %d,sub-rank %d\n",rank,subsize,subrank); 1257 ierr = PetscSynchronizedFlush(comm,PETSC_STDOUT);CHKERRQ(ierr); 1258 */ 1259 1260 /* create dummy vectors xsub and ysub */ 1261 ierr = MatGetLocalSize(mpjac->submats,&m,&n);CHKERRQ(ierr); 1262 ierr = VecCreateMPIWithArray(subcomm,1,n,PETSC_DECIDE,NULL,&mpjac->xsub);CHKERRQ(ierr); 1263 ierr = VecCreateMPIWithArray(subcomm,1,m,PETSC_DECIDE,NULL,&mpjac->ysub);CHKERRQ(ierr); 1264 #ifdef PETSC_HAVE_CUSP 1265 ierr = VecSetType(mpjac->xsub,VECMPICUSP);CHKERRQ(ierr); 1266 ierr = VecSetType(mpjac->ysub,VECMPICUSP);CHKERRQ(ierr); 1267 #endif 1268 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)mpjac->xsub);CHKERRQ(ierr); 1269 ierr = PetscLogObjectParent((PetscObject)pc,(PetscObject)mpjac->ysub);CHKERRQ(ierr); 1270 1271 pc->ops->reset = PCReset_BJacobi_Multiproc; 1272 pc->ops->destroy = PCDestroy_BJacobi_Multiproc; 1273 pc->ops->apply = PCApply_BJacobi_Multiproc; 1274 } else { /* pc->setupcalled */ 1275 subcomm = PetscSubcommChild(mpjac->psubcomm); 1276 if (pc->flag == DIFFERENT_NONZERO_PATTERN) { 1277 /* destroy old matrix blocks, then get new matrix blocks */ 1278 if (mpjac->submats) {ierr = MatDestroy(&mpjac->submats);CHKERRQ(ierr);} 1279 ierr = (*pc->pmat->ops->getmultiprocblock)(pc->pmat,subcomm,MAT_INITIAL_MATRIX,&mpjac->submats);CHKERRQ(ierr); 1280 } else { 1281 ierr = (*pc->pmat->ops->getmultiprocblock)(pc->pmat,subcomm,MAT_REUSE_MATRIX,&mpjac->submats);CHKERRQ(ierr); 1282 } 1283 ierr = KSPSetOperators(jac->ksp[0],mpjac->submats,mpjac->submats);CHKERRQ(ierr); 1284 } 1285 1286 if (!wasSetup && pc->setfromoptionscalled) { 1287 ierr = KSPSetFromOptions(jac->ksp[0]);CHKERRQ(ierr); 1288 } 1289 PetscFunctionReturn(0); 1290 } 1291