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