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 = VecResetArray(bjac->x);CHKERRQ(ierr); 776 ierr = VecResetArray(bjac->y);CHKERRQ(ierr); 777 ierr = VecRestoreArray(x,&x_array);CHKERRQ(ierr); 778 ierr = VecRestoreArray(y,&y_array);CHKERRQ(ierr); 779 PetscFunctionReturn(0); 780 } 781 782 #undef __FUNCT__ 783 #define __FUNCT__ "PCApplySymmetricLeft_BJacobi_Singleblock" 784 PetscErrorCode PCApplySymmetricLeft_BJacobi_Singleblock(PC pc,Vec x,Vec y) 785 { 786 PetscErrorCode ierr; 787 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 788 PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data; 789 PetscScalar *x_array,*y_array; 790 PC subpc; 791 792 PetscFunctionBegin; 793 /* 794 The VecPlaceArray() is to avoid having to copy the 795 y vector into the bjac->x vector. The reason for 796 the bjac->x vector is that we need a sequential vector 797 for the sequential solve. 798 */ 799 ierr = VecGetArray(x,&x_array);CHKERRQ(ierr); 800 ierr = VecGetArray(y,&y_array);CHKERRQ(ierr); 801 ierr = VecPlaceArray(bjac->x,x_array);CHKERRQ(ierr); 802 ierr = VecPlaceArray(bjac->y,y_array);CHKERRQ(ierr); 803 804 /* apply the symmetric left portion of the inner PC operator */ 805 /* note this by-passes the inner KSP and its options completely */ 806 807 ierr = KSPGetPC(jac->ksp[0],&subpc);CHKERRQ(ierr); 808 ierr = PCApplySymmetricLeft(subpc,bjac->x,bjac->y);CHKERRQ(ierr); 809 810 ierr = VecRestoreArray(x,&x_array);CHKERRQ(ierr); 811 ierr = VecRestoreArray(y,&y_array);CHKERRQ(ierr); 812 PetscFunctionReturn(0); 813 } 814 815 #undef __FUNCT__ 816 #define __FUNCT__ "PCApplySymmetricRight_BJacobi_Singleblock" 817 PetscErrorCode PCApplySymmetricRight_BJacobi_Singleblock(PC pc,Vec x,Vec y) 818 { 819 PetscErrorCode ierr; 820 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 821 PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data; 822 PetscScalar *x_array,*y_array; 823 PC subpc; 824 825 PetscFunctionBegin; 826 /* 827 The VecPlaceArray() is to avoid having to copy the 828 y vector into the bjac->x vector. The reason for 829 the bjac->x vector is that we need a sequential vector 830 for the sequential solve. 831 */ 832 ierr = VecGetArray(x,&x_array);CHKERRQ(ierr); 833 ierr = VecGetArray(y,&y_array);CHKERRQ(ierr); 834 ierr = VecPlaceArray(bjac->x,x_array);CHKERRQ(ierr); 835 ierr = VecPlaceArray(bjac->y,y_array);CHKERRQ(ierr); 836 837 /* apply the symmetric right portion of the inner PC operator */ 838 /* note this by-passes the inner KSP and its options completely */ 839 840 ierr = KSPGetPC(jac->ksp[0],&subpc);CHKERRQ(ierr); 841 ierr = PCApplySymmetricRight(subpc,bjac->x,bjac->y);CHKERRQ(ierr); 842 843 ierr = VecRestoreArray(x,&x_array);CHKERRQ(ierr); 844 ierr = VecRestoreArray(y,&y_array);CHKERRQ(ierr); 845 PetscFunctionReturn(0); 846 } 847 848 #undef __FUNCT__ 849 #define __FUNCT__ "PCApplyTranspose_BJacobi_Singleblock" 850 PetscErrorCode PCApplyTranspose_BJacobi_Singleblock(PC pc,Vec x,Vec y) 851 { 852 PetscErrorCode ierr; 853 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 854 PC_BJacobi_Singleblock *bjac = (PC_BJacobi_Singleblock*)jac->data; 855 PetscScalar *x_array,*y_array; 856 857 PetscFunctionBegin; 858 /* 859 The VecPlaceArray() is to avoid having to copy the 860 y vector into the bjac->x vector. The reason for 861 the bjac->x vector is that we need a sequential vector 862 for the sequential solve. 863 */ 864 ierr = VecGetArray(x,&x_array);CHKERRQ(ierr); 865 ierr = VecGetArray(y,&y_array);CHKERRQ(ierr); 866 ierr = VecPlaceArray(bjac->x,x_array);CHKERRQ(ierr); 867 ierr = VecPlaceArray(bjac->y,y_array);CHKERRQ(ierr); 868 ierr = KSPSolveTranspose(jac->ksp[0],bjac->x,bjac->y);CHKERRQ(ierr); 869 ierr = VecRestoreArray(x,&x_array);CHKERRQ(ierr); 870 ierr = VecRestoreArray(y,&y_array);CHKERRQ(ierr); 871 PetscFunctionReturn(0); 872 } 873 874 #undef __FUNCT__ 875 #define __FUNCT__ "PCSetUp_BJacobi_Singleblock" 876 static PetscErrorCode PCSetUp_BJacobi_Singleblock(PC pc,Mat mat,Mat pmat) 877 { 878 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 879 PetscErrorCode ierr; 880 PetscInt m; 881 KSP ksp; 882 Vec x,y; 883 PC_BJacobi_Singleblock *bjac; 884 PC subpc; 885 886 PetscFunctionBegin; 887 888 /* set default direct solver with no Krylov method */ 889 if (!pc->setupcalled) { 890 const char *prefix; 891 ierr = KSPCreate(PETSC_COMM_SELF,&ksp);CHKERRQ(ierr); 892 ierr = PetscLogObjectParent(pc,ksp);CHKERRQ(ierr); 893 ierr = KSPSetType(ksp,KSPPREONLY);CHKERRQ(ierr); 894 ierr = KSPGetPC(ksp,&subpc);CHKERRQ(ierr); 895 ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr); 896 ierr = KSPSetOptionsPrefix(ksp,prefix);CHKERRQ(ierr); 897 ierr = KSPAppendOptionsPrefix(ksp,"sub_");CHKERRQ(ierr); 898 /* 899 The reason we need to generate these vectors is to serve 900 as the right-hand side and solution vector for the solve on the 901 block. We do not need to allocate space for the vectors since 902 that is provided via VecPlaceArray() just before the call to 903 KSPSolve() on the block. 904 */ 905 ierr = MatGetSize(pmat,&m,&m);CHKERRQ(ierr); 906 ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,m,PETSC_NULL,&x);CHKERRQ(ierr); 907 ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,m,PETSC_NULL,&y);CHKERRQ(ierr); 908 ierr = PetscLogObjectParent(pc,x);CHKERRQ(ierr); 909 ierr = PetscLogObjectParent(pc,y);CHKERRQ(ierr); 910 911 pc->ops->destroy = PCDestroy_BJacobi_Singleblock; 912 pc->ops->apply = PCApply_BJacobi_Singleblock; 913 pc->ops->applysymmetricleft = PCApplySymmetricLeft_BJacobi_Singleblock; 914 pc->ops->applysymmetricright = PCApplySymmetricRight_BJacobi_Singleblock; 915 pc->ops->applytranspose = PCApplyTranspose_BJacobi_Singleblock; 916 pc->ops->setuponblocks = PCSetUpOnBlocks_BJacobi_Singleblock; 917 918 ierr = PetscMalloc(sizeof(PC_BJacobi_Singleblock),&bjac);CHKERRQ(ierr); 919 ierr = PetscLogObjectMemory(pc,sizeof(PC_BJacobi_Singleblock));CHKERRQ(ierr); 920 bjac->x = x; 921 bjac->y = y; 922 923 ierr = PetscMalloc(sizeof(KSP),&jac->ksp);CHKERRQ(ierr); 924 jac->ksp[0] = ksp; 925 jac->data = (void*)bjac; 926 } else { 927 ksp = jac->ksp[0]; 928 bjac = (PC_BJacobi_Singleblock *)jac->data; 929 } 930 if (jac->use_true_local) { 931 ierr = KSPSetOperators(ksp,mat,pmat,pc->flag);CHKERRQ(ierr); 932 } else { 933 ierr = KSPSetOperators(ksp,pmat,pmat,pc->flag);CHKERRQ(ierr); 934 } 935 ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); 936 PetscFunctionReturn(0); 937 } 938 939 /* ---------------------------------------------------------------------------------------------*/ 940 941 #undef __FUNCT__ 942 #define __FUNCT__ "PCDestroy_BJacobi_Multiblock" 943 PetscErrorCode PCDestroy_BJacobi_Multiblock(PC pc) 944 { 945 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 946 PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data; 947 PetscErrorCode ierr; 948 PetscInt i; 949 950 PetscFunctionBegin; 951 ierr = MatDestroyMatrices(jac->n_local,&bjac->pmat);CHKERRQ(ierr); 952 if (jac->use_true_local) { 953 ierr = MatDestroyMatrices(jac->n_local,&bjac->mat);CHKERRQ(ierr); 954 } 955 956 /* 957 If the on processor block had to be generated via a MatGetDiagonalBlock() 958 that creates a copy (for example MPIBDiag matrices do), this frees the space 959 */ 960 if (jac->tp_mat) { 961 ierr = MatDestroy(jac->tp_mat);CHKERRQ(ierr); 962 } 963 if (jac->tp_pmat) { 964 ierr = MatDestroy(jac->tp_pmat);CHKERRQ(ierr); 965 } 966 967 for (i=0; i<jac->n_local; i++) { 968 ierr = KSPDestroy(jac->ksp[i]);CHKERRQ(ierr); 969 ierr = VecDestroy(bjac->x[i]);CHKERRQ(ierr); 970 ierr = VecDestroy(bjac->y[i]);CHKERRQ(ierr); 971 ierr = ISDestroy(bjac->is[i]);CHKERRQ(ierr); 972 } 973 ierr = PetscFree(jac->ksp);CHKERRQ(ierr); 974 ierr = PetscFree(bjac->x);CHKERRQ(ierr); 975 ierr = PetscFree(bjac->starts);CHKERRQ(ierr); 976 ierr = PetscFree(bjac->is);CHKERRQ(ierr); 977 ierr = PetscFree(bjac);CHKERRQ(ierr); 978 if (jac->l_lens) {ierr = PetscFree(jac->l_lens);CHKERRQ(ierr);} 979 if (jac->g_lens) {ierr = PetscFree(jac->g_lens);CHKERRQ(ierr);} 980 ierr = PetscFree(jac);CHKERRQ(ierr); 981 PetscFunctionReturn(0); 982 } 983 984 #undef __FUNCT__ 985 #define __FUNCT__ "PCSetUpOnBlocks_BJacobi_Multiblock" 986 PetscErrorCode PCSetUpOnBlocks_BJacobi_Multiblock(PC pc) 987 { 988 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 989 PetscErrorCode ierr; 990 PetscInt i,n_local = jac->n_local; 991 992 PetscFunctionBegin; 993 for (i=0; i<n_local; i++) { 994 ierr = KSPSetUp(jac->ksp[i]);CHKERRQ(ierr); 995 } 996 PetscFunctionReturn(0); 997 } 998 999 /* 1000 Preconditioner for block Jacobi 1001 */ 1002 #undef __FUNCT__ 1003 #define __FUNCT__ "PCApply_BJacobi_Multiblock" 1004 PetscErrorCode PCApply_BJacobi_Multiblock(PC pc,Vec x,Vec y) 1005 { 1006 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 1007 PetscErrorCode ierr; 1008 PetscInt i,n_local = jac->n_local; 1009 PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data; 1010 PetscScalar *xin,*yin; 1011 static PetscTruth flag = PETSC_TRUE; 1012 static PetscEvent SUBKspSolve; 1013 1014 PetscFunctionBegin; 1015 if (flag) { 1016 ierr = PetscLogEventRegister(&SUBKspSolve,"SubKspSolve",KSP_COOKIE);CHKERRQ(ierr); 1017 flag = PETSC_FALSE; 1018 } 1019 ierr = VecGetArray(x,&xin);CHKERRQ(ierr); 1020 ierr = VecGetArray(y,&yin);CHKERRQ(ierr); 1021 for (i=0; i<n_local; i++) { 1022 /* 1023 To avoid copying the subvector from x into a workspace we instead 1024 make the workspace vector array point to the subpart of the array of 1025 the global vector. 1026 */ 1027 ierr = VecPlaceArray(bjac->x[i],xin+bjac->starts[i]);CHKERRQ(ierr); 1028 ierr = VecPlaceArray(bjac->y[i],yin+bjac->starts[i]);CHKERRQ(ierr); 1029 1030 ierr = PetscLogEventBegin(SUBKspSolve,jac->ksp[i],bjac->x[i],bjac->y[i],0);CHKERRQ(ierr); 1031 ierr = KSPSolve(jac->ksp[i],bjac->x[i],bjac->y[i]);CHKERRQ(ierr); 1032 ierr = PetscLogEventEnd(SUBKspSolve,jac->ksp[i],bjac->x[i],bjac->y[i],0);CHKERRQ(ierr); 1033 } 1034 ierr = VecRestoreArray(x,&xin);CHKERRQ(ierr); 1035 ierr = VecRestoreArray(y,&yin);CHKERRQ(ierr); 1036 PetscFunctionReturn(0); 1037 } 1038 1039 /* 1040 Preconditioner for block Jacobi 1041 */ 1042 #undef __FUNCT__ 1043 #define __FUNCT__ "PCApplyTranspose_BJacobi_Multiblock" 1044 PetscErrorCode PCApplyTranspose_BJacobi_Multiblock(PC pc,Vec x,Vec y) 1045 { 1046 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 1047 PetscErrorCode ierr; 1048 PetscInt i,n_local = jac->n_local; 1049 PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data; 1050 PetscScalar *xin,*yin; 1051 static PetscTruth flag = PETSC_TRUE; 1052 static PetscEvent SUBKspSolve; 1053 1054 PetscFunctionBegin; 1055 if (flag) { 1056 ierr = PetscLogEventRegister(&SUBKspSolve,"SubKspSolveTranspose",KSP_COOKIE);CHKERRQ(ierr); 1057 flag = PETSC_FALSE; 1058 } 1059 ierr = VecGetArray(x,&xin);CHKERRQ(ierr); 1060 ierr = VecGetArray(y,&yin);CHKERRQ(ierr); 1061 for (i=0; i<n_local; i++) { 1062 /* 1063 To avoid copying the subvector from x into a workspace we instead 1064 make the workspace vector array point to the subpart of the array of 1065 the global vector. 1066 */ 1067 ierr = VecPlaceArray(bjac->x[i],xin+bjac->starts[i]);CHKERRQ(ierr); 1068 ierr = VecPlaceArray(bjac->y[i],yin+bjac->starts[i]);CHKERRQ(ierr); 1069 1070 ierr = PetscLogEventBegin(SUBKspSolve,jac->ksp[i],bjac->x[i],bjac->y[i],0);CHKERRQ(ierr); 1071 ierr = KSPSolveTranspose(jac->ksp[i],bjac->x[i],bjac->y[i]);CHKERRQ(ierr); 1072 ierr = PetscLogEventEnd(SUBKspSolve,jac->ksp[i],bjac->x[i],bjac->y[i],0);CHKERRQ(ierr); 1073 } 1074 ierr = VecRestoreArray(x,&xin);CHKERRQ(ierr); 1075 ierr = VecRestoreArray(y,&yin);CHKERRQ(ierr); 1076 PetscFunctionReturn(0); 1077 } 1078 1079 #undef __FUNCT__ 1080 #define __FUNCT__ "PCSetUp_BJacobi_Multiblock" 1081 static PetscErrorCode PCSetUp_BJacobi_Multiblock(PC pc,Mat mat,Mat pmat) 1082 { 1083 PC_BJacobi *jac = (PC_BJacobi*)pc->data; 1084 PetscErrorCode ierr; 1085 PetscInt m,n_local,N,M,start,i; 1086 const char *prefix,*pprefix,*mprefix; 1087 KSP ksp; 1088 Vec x,y; 1089 PC_BJacobi_Multiblock *bjac = (PC_BJacobi_Multiblock*)jac->data; 1090 PC subpc; 1091 IS is; 1092 MatReuse scall = MAT_REUSE_MATRIX; 1093 1094 PetscFunctionBegin; 1095 ierr = MatGetLocalSize(pc->pmat,&M,&N);CHKERRQ(ierr); 1096 1097 n_local = jac->n_local; 1098 1099 if (jac->use_true_local) { 1100 if (mat->type != pmat->type) SETERRQ(PETSC_ERR_ARG_INCOMP,"Matrices not of same type"); 1101 } 1102 1103 /* set default direct solver with no Krylov method */ 1104 if (!pc->setupcalled) { 1105 scall = MAT_INITIAL_MATRIX; 1106 pc->ops->destroy = PCDestroy_BJacobi_Multiblock; 1107 pc->ops->apply = PCApply_BJacobi_Multiblock; 1108 pc->ops->applytranspose= PCApplyTranspose_BJacobi_Multiblock; 1109 pc->ops->setuponblocks = PCSetUpOnBlocks_BJacobi_Multiblock; 1110 1111 ierr = PetscMalloc(sizeof(PC_BJacobi_Multiblock),&bjac);CHKERRQ(ierr); 1112 ierr = PetscLogObjectMemory(pc,sizeof(PC_BJacobi_Multiblock));CHKERRQ(ierr); 1113 ierr = PetscMalloc(n_local*sizeof(KSP),&jac->ksp);CHKERRQ(ierr); 1114 ierr = PetscLogObjectMemory(pc,sizeof(n_local*sizeof(KSP)));CHKERRQ(ierr); 1115 ierr = PetscMalloc(2*n_local*sizeof(Vec),&bjac->x);CHKERRQ(ierr); 1116 ierr = PetscLogObjectMemory(pc,sizeof(2*n_local*sizeof(Vec)));CHKERRQ(ierr); 1117 bjac->y = bjac->x + n_local; 1118 ierr = PetscMalloc(n_local*sizeof(PetscScalar),&bjac->starts);CHKERRQ(ierr); 1119 ierr = PetscLogObjectMemory(pc,sizeof(n_local*sizeof(PetscScalar)));CHKERRQ(ierr); 1120 1121 jac->data = (void*)bjac; 1122 ierr = PetscMalloc(n_local*sizeof(IS),&bjac->is);CHKERRQ(ierr); 1123 ierr = PetscLogObjectMemory(pc,sizeof(n_local*sizeof(IS)));CHKERRQ(ierr); 1124 1125 start = 0; 1126 for (i=0; i<n_local; i++) { 1127 ierr = KSPCreate(PETSC_COMM_SELF,&ksp);CHKERRQ(ierr); 1128 ierr = PetscLogObjectParent(pc,ksp);CHKERRQ(ierr); 1129 ierr = KSPSetType(ksp,KSPPREONLY);CHKERRQ(ierr); 1130 ierr = KSPGetPC(ksp,&subpc);CHKERRQ(ierr); 1131 ierr = PCGetOptionsPrefix(pc,&prefix);CHKERRQ(ierr); 1132 ierr = KSPSetOptionsPrefix(ksp,prefix);CHKERRQ(ierr); 1133 ierr = KSPAppendOptionsPrefix(ksp,"sub_");CHKERRQ(ierr); 1134 1135 m = jac->l_lens[i]; 1136 1137 /* 1138 The reason we need to generate these vectors is to serve 1139 as the right-hand side and solution vector for the solve on the 1140 block. We do not need to allocate space for the vectors since 1141 that is provided via VecPlaceArray() just before the call to 1142 KSPSolve() on the block. 1143 1144 */ 1145 ierr = VecCreateSeq(PETSC_COMM_SELF,m,&x);CHKERRQ(ierr); 1146 ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,m,PETSC_NULL,&y);CHKERRQ(ierr); 1147 ierr = PetscLogObjectParent(pc,x);CHKERRQ(ierr); 1148 ierr = PetscLogObjectParent(pc,y);CHKERRQ(ierr); 1149 bjac->x[i] = x; 1150 bjac->y[i] = y; 1151 bjac->starts[i] = start; 1152 jac->ksp[i] = ksp; 1153 1154 ierr = ISCreateStride(PETSC_COMM_SELF,m,start,1,&is);CHKERRQ(ierr); 1155 bjac->is[i] = is; 1156 ierr = PetscLogObjectParent(pc,is);CHKERRQ(ierr); 1157 1158 start += m; 1159 } 1160 } else { 1161 bjac = (PC_BJacobi_Multiblock*)jac->data; 1162 /* 1163 Destroy the blocks from the previous iteration 1164 */ 1165 if (pc->flag == DIFFERENT_NONZERO_PATTERN) { 1166 ierr = MatDestroyMatrices(n_local,&bjac->pmat);CHKERRQ(ierr); 1167 if (jac->use_true_local) { 1168 ierr = MatDestroyMatrices(n_local,&bjac->mat);CHKERRQ(ierr); 1169 } 1170 scall = MAT_INITIAL_MATRIX; 1171 } 1172 } 1173 1174 ierr = MatGetSubMatrices(pmat,n_local,bjac->is,bjac->is,scall,&bjac->pmat);CHKERRQ(ierr); 1175 if (jac->use_true_local) { 1176 ierr = PetscObjectGetOptionsPrefix((PetscObject)mat,&mprefix);CHKERRQ(ierr); 1177 ierr = MatGetSubMatrices(mat,n_local,bjac->is,bjac->is,scall,&bjac->mat);CHKERRQ(ierr); 1178 } 1179 /* Return control to the user so that the submatrices can be modified (e.g., to apply 1180 different boundary conditions for the submatrices than for the global problem) */ 1181 ierr = PCModifySubMatrices(pc,n_local,bjac->is,bjac->is,bjac->pmat,pc->modifysubmatricesP);CHKERRQ(ierr); 1182 1183 ierr = PetscObjectGetOptionsPrefix((PetscObject)pmat,&pprefix);CHKERRQ(ierr); 1184 for (i=0; i<n_local; i++) { 1185 ierr = PetscLogObjectParent(pc,bjac->pmat[i]);CHKERRQ(ierr); 1186 ierr = PetscObjectSetOptionsPrefix((PetscObject)bjac->pmat[i],pprefix);CHKERRQ(ierr); 1187 if (jac->use_true_local) { 1188 ierr = PetscLogObjectParent(pc,bjac->mat[i]);CHKERRQ(ierr); 1189 ierr = PetscObjectSetOptionsPrefix((PetscObject)bjac->mat[i],mprefix);CHKERRQ(ierr); 1190 ierr = KSPSetOperators(jac->ksp[i],bjac->mat[i],bjac->pmat[i],pc->flag);CHKERRQ(ierr); 1191 } else { 1192 ierr = KSPSetOperators(jac->ksp[i],bjac->pmat[i],bjac->pmat[i],pc->flag);CHKERRQ(ierr); 1193 } 1194 ierr = KSPSetFromOptions(jac->ksp[i]);CHKERRQ(ierr); 1195 } 1196 1197 PetscFunctionReturn(0); 1198 } 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209