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