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