1 /* TODOLIST 2 Remove PetscOptionsSetValue for pcis! 3 DofSplitting and DM attached to pc? 4 Change SetNeumannBoundaries to SetNeumannBoundariesLocal and provide new SetNeumannBoundaries (same Dirichlet) 5 BDDC with MG framework? 6 provide other ops? Ask to developers 7 man pages 8 */ 9 10 /* ---------------------------------------------------------------------------------------------------------------------------------------------- 11 Implementation of BDDC preconditioner based on: 12 C. Dohrmann "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007 13 ---------------------------------------------------------------------------------------------------------------------------------------------- */ 14 15 #include "bddc.h" /*I "petscpc.h" I*/ /* includes for fortran wrappers */ 16 #include "bddcprivate.h" 17 #include <petscblaslapack.h> 18 19 /* -------------------------------------------------------------------------- */ 20 #undef __FUNCT__ 21 #define __FUNCT__ "PCSetFromOptions_BDDC" 22 PetscErrorCode PCSetFromOptions_BDDC(PC pc) 23 { 24 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 25 PetscErrorCode ierr; 26 27 PetscFunctionBegin; 28 ierr = PetscOptionsHead("BDDC options");CHKERRQ(ierr); 29 /* Verbose debugging */ 30 ierr = PetscOptionsInt("-pc_bddc_check_level","Verbose output for PCBDDC (intended for debug)","none",pcbddc->dbg_flag,&pcbddc->dbg_flag,NULL);CHKERRQ(ierr); 31 /* Primal space cumstomization */ 32 ierr = PetscOptionsBool("-pc_bddc_use_vertices","Use or not corner dofs in coarse space","none",pcbddc->use_vertices,&pcbddc->use_vertices,NULL);CHKERRQ(ierr); 33 ierr = PetscOptionsBool("-pc_bddc_use_edges","Use or not edge constraints in coarse space","none",pcbddc->use_edges,&pcbddc->use_edges,NULL);CHKERRQ(ierr); 34 ierr = PetscOptionsBool("-pc_bddc_use_faces","Use or not face constraints in coarse space","none",pcbddc->use_faces,&pcbddc->use_faces,NULL);CHKERRQ(ierr); 35 /* Change of basis */ 36 ierr = PetscOptionsBool("-pc_bddc_use_change_of_basis","Use or not change of basis on local edge nodes","none",pcbddc->use_change_of_basis,&pcbddc->use_change_of_basis,NULL);CHKERRQ(ierr); 37 ierr = PetscOptionsBool("-pc_bddc_use_change_on_faces","Use or not change of basis on local face nodes","none",pcbddc->use_change_on_faces,&pcbddc->use_change_on_faces,NULL);CHKERRQ(ierr); 38 if (!pcbddc->use_change_of_basis) { 39 pcbddc->use_change_on_faces = PETSC_FALSE; 40 } 41 /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */ 42 ierr = PetscOptionsBool("-pc_bddc_switch_static","Switch on static condensation ops around the interface preconditioner","none",pcbddc->switch_static,&pcbddc->switch_static,NULL);CHKERRQ(ierr); 43 ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","none",pcbddc->coarsening_ratio,&pcbddc->coarsening_ratio,NULL);CHKERRQ(ierr); 44 ierr = PetscOptionsInt("-pc_bddc_levels","Set maximum number of levels for multilevel","none",pcbddc->max_levels,&pcbddc->max_levels,NULL);CHKERRQ(ierr); 45 ierr = PetscOptionsBool("-pc_bddc_use_deluxe_scaling","Use deluxe scaling for BDDC","none",pcbddc->use_deluxe_scaling,&pcbddc->use_deluxe_scaling,NULL);CHKERRQ(ierr); 46 ierr = PetscOptionsTail();CHKERRQ(ierr); 47 PetscFunctionReturn(0); 48 } 49 /* -------------------------------------------------------------------------- */ 50 #undef __FUNCT__ 51 #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS_BDDC" 52 static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices) 53 { 54 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 55 PetscErrorCode ierr; 56 57 PetscFunctionBegin; 58 ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr); 59 ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr); 60 pcbddc->user_primal_vertices = PrimalVertices; 61 PetscFunctionReturn(0); 62 } 63 #undef __FUNCT__ 64 #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS" 65 /*@ 66 PCBDDCSetPrimalVerticesLocalIS - Set user defined primal vertices in PCBDDC. 67 68 Not collective 69 70 Input Parameters: 71 + pc - the preconditioning context 72 - PrimalVertices - index sets of primal vertices in local numbering 73 74 Level: intermediate 75 76 Notes: 77 78 .seealso: PCBDDC 79 @*/ 80 PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices) 81 { 82 PetscErrorCode ierr; 83 84 PetscFunctionBegin; 85 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 86 PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2); 87 ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr); 88 PetscFunctionReturn(0); 89 } 90 /* -------------------------------------------------------------------------- */ 91 #undef __FUNCT__ 92 #define __FUNCT__ "PCBDDCSetCoarseningRatio_BDDC" 93 static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k) 94 { 95 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 96 97 PetscFunctionBegin; 98 pcbddc->coarsening_ratio = k; 99 PetscFunctionReturn(0); 100 } 101 102 #undef __FUNCT__ 103 #define __FUNCT__ "PCBDDCSetCoarseningRatio" 104 /*@ 105 PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel coarsening 106 107 Logically collective on PC 108 109 Input Parameters: 110 + pc - the preconditioning context 111 - k - coarsening ratio 112 113 Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level. 114 115 Level: intermediate 116 117 Notes: 118 119 .seealso: PCBDDC 120 @*/ 121 PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k) 122 { 123 PetscErrorCode ierr; 124 125 PetscFunctionBegin; 126 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 127 PetscValidLogicalCollectiveInt(pc,k,2); 128 ierr = PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));CHKERRQ(ierr); 129 PetscFunctionReturn(0); 130 } 131 132 /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */ 133 #undef __FUNCT__ 134 #define __FUNCT__ "PCBDDCSetUseExactDirichlet_BDDC" 135 static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc,PetscBool flg) 136 { 137 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 138 139 PetscFunctionBegin; 140 pcbddc->use_exact_dirichlet = flg; 141 PetscFunctionReturn(0); 142 } 143 144 #undef __FUNCT__ 145 #define __FUNCT__ "PCBDDCSetUseExactDirichlet" 146 PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool flg) 147 { 148 PetscErrorCode ierr; 149 150 PetscFunctionBegin; 151 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 152 PetscValidLogicalCollectiveBool(pc,flg,2); 153 ierr = PetscTryMethod(pc,"PCBDDCSetUseExactDirichlet_C",(PC,PetscBool),(pc,flg));CHKERRQ(ierr); 154 PetscFunctionReturn(0); 155 } 156 157 #undef __FUNCT__ 158 #define __FUNCT__ "PCBDDCSetLevel_BDDC" 159 static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc,PetscInt level) 160 { 161 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 162 163 PetscFunctionBegin; 164 pcbddc->current_level = level; 165 PetscFunctionReturn(0); 166 } 167 168 #undef __FUNCT__ 169 #define __FUNCT__ "PCBDDCSetLevel" 170 PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level) 171 { 172 PetscErrorCode ierr; 173 174 PetscFunctionBegin; 175 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 176 PetscValidLogicalCollectiveInt(pc,level,2); 177 ierr = PetscTryMethod(pc,"PCBDDCSetLevel_C",(PC,PetscInt),(pc,level));CHKERRQ(ierr); 178 PetscFunctionReturn(0); 179 } 180 181 #undef __FUNCT__ 182 #define __FUNCT__ "PCBDDCSetLevels_BDDC" 183 static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc,PetscInt levels) 184 { 185 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 186 187 PetscFunctionBegin; 188 pcbddc->max_levels = levels; 189 PetscFunctionReturn(0); 190 } 191 192 #undef __FUNCT__ 193 #define __FUNCT__ "PCBDDCSetLevels" 194 /*@ 195 PCBDDCSetLevels - Sets the maximum number of levels within the multilevel approach. 196 197 Logically collective on PC 198 199 Input Parameters: 200 + pc - the preconditioning context 201 - levels - the maximum number of levels 202 203 Default value is 0, i.e. coarse problem will be solved exactly 204 205 Level: intermediate 206 207 Notes: 208 209 .seealso: PCBDDC 210 @*/ 211 PetscErrorCode PCBDDCSetLevels(PC pc,PetscInt levels) 212 { 213 PetscErrorCode ierr; 214 215 PetscFunctionBegin; 216 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 217 PetscValidLogicalCollectiveInt(pc,levels,2); 218 ierr = PetscTryMethod(pc,"PCBDDCSetLevels_C",(PC,PetscInt),(pc,levels));CHKERRQ(ierr); 219 PetscFunctionReturn(0); 220 } 221 /* -------------------------------------------------------------------------- */ 222 223 #undef __FUNCT__ 224 #define __FUNCT__ "PCBDDCSetNullSpace_BDDC" 225 static PetscErrorCode PCBDDCSetNullSpace_BDDC(PC pc,MatNullSpace NullSpace) 226 { 227 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 228 PetscErrorCode ierr; 229 230 PetscFunctionBegin; 231 ierr = PetscObjectReference((PetscObject)NullSpace);CHKERRQ(ierr); 232 ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr); 233 pcbddc->NullSpace = NullSpace; 234 PetscFunctionReturn(0); 235 } 236 237 #undef __FUNCT__ 238 #define __FUNCT__ "PCBDDCSetNullSpace" 239 /*@ 240 PCBDDCSetNullSpace - Set NullSpace of global operator of BDDC preconditioned mat. 241 242 Logically collective on PC and MatNullSpace 243 244 Input Parameters: 245 + pc - the preconditioning context 246 - NullSpace - Null space of the linear operator to be preconditioned. 247 248 Level: intermediate 249 250 Notes: 251 252 .seealso: PCBDDC 253 @*/ 254 PetscErrorCode PCBDDCSetNullSpace(PC pc,MatNullSpace NullSpace) 255 { 256 PetscErrorCode ierr; 257 258 PetscFunctionBegin; 259 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 260 PetscValidHeaderSpecific(NullSpace,MAT_NULLSPACE_CLASSID,2); 261 PetscCheckSameComm(pc,1,NullSpace,2); 262 ierr = PetscTryMethod(pc,"PCBDDCSetNullSpace_C",(PC,MatNullSpace),(pc,NullSpace));CHKERRQ(ierr); 263 PetscFunctionReturn(0); 264 } 265 /* -------------------------------------------------------------------------- */ 266 267 #undef __FUNCT__ 268 #define __FUNCT__ "PCBDDCSetDirichletBoundaries_BDDC" 269 static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries) 270 { 271 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 272 PetscErrorCode ierr; 273 274 PetscFunctionBegin; 275 ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr); 276 ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr); 277 pcbddc->DirichletBoundaries=DirichletBoundaries; 278 PetscFunctionReturn(0); 279 } 280 281 #undef __FUNCT__ 282 #define __FUNCT__ "PCBDDCSetDirichletBoundaries" 283 /*@ 284 PCBDDCSetDirichletBoundaries - Set index set defining subdomain part (in local ordering) 285 of Dirichlet boundaries for the global problem. 286 287 Not collective 288 289 Input Parameters: 290 + pc - the preconditioning context 291 - DirichletBoundaries - sequential index set defining the subdomain part of Dirichlet boundaries (can be NULL) 292 293 Level: intermediate 294 295 Notes: 296 297 .seealso: PCBDDC 298 @*/ 299 PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries) 300 { 301 PetscErrorCode ierr; 302 303 PetscFunctionBegin; 304 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 305 PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2); 306 ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr); 307 PetscFunctionReturn(0); 308 } 309 /* -------------------------------------------------------------------------- */ 310 311 #undef __FUNCT__ 312 #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC" 313 static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries) 314 { 315 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 316 PetscErrorCode ierr; 317 318 PetscFunctionBegin; 319 ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr); 320 ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr); 321 pcbddc->NeumannBoundaries=NeumannBoundaries; 322 PetscFunctionReturn(0); 323 } 324 325 #undef __FUNCT__ 326 #define __FUNCT__ "PCBDDCSetNeumannBoundaries" 327 /*@ 328 PCBDDCSetNeumannBoundaries - Set index set defining subdomain part (in local ordering) 329 of Neumann boundaries for the global problem. 330 331 Not collective 332 333 Input Parameters: 334 + pc - the preconditioning context 335 - NeumannBoundaries - sequential index set defining the subdomain part of Neumann boundaries (can be NULL) 336 337 Level: intermediate 338 339 Notes: 340 341 .seealso: PCBDDC 342 @*/ 343 PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries) 344 { 345 PetscErrorCode ierr; 346 347 PetscFunctionBegin; 348 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 349 PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2); 350 ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr); 351 PetscFunctionReturn(0); 352 } 353 /* -------------------------------------------------------------------------- */ 354 355 #undef __FUNCT__ 356 #define __FUNCT__ "PCBDDCGetDirichletBoundaries_BDDC" 357 static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries) 358 { 359 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 360 361 PetscFunctionBegin; 362 *DirichletBoundaries = pcbddc->DirichletBoundaries; 363 PetscFunctionReturn(0); 364 } 365 366 #undef __FUNCT__ 367 #define __FUNCT__ "PCBDDCGetDirichletBoundaries" 368 /*@ 369 PCBDDCGetDirichletBoundaries - Get index set defining subdomain part (in local ordering) 370 of Dirichlet boundaries for the global problem. 371 372 Not collective 373 374 Input Parameters: 375 + pc - the preconditioning context 376 377 Output Parameters: 378 + DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries 379 380 Level: intermediate 381 382 Notes: 383 384 .seealso: PCBDDC 385 @*/ 386 PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries) 387 { 388 PetscErrorCode ierr; 389 390 PetscFunctionBegin; 391 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 392 ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr); 393 PetscFunctionReturn(0); 394 } 395 /* -------------------------------------------------------------------------- */ 396 397 #undef __FUNCT__ 398 #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC" 399 static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries) 400 { 401 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 402 403 PetscFunctionBegin; 404 *NeumannBoundaries = pcbddc->NeumannBoundaries; 405 PetscFunctionReturn(0); 406 } 407 408 #undef __FUNCT__ 409 #define __FUNCT__ "PCBDDCGetNeumannBoundaries" 410 /*@ 411 PCBDDCGetNeumannBoundaries - Get index set defining subdomain part (in local ordering) 412 of Neumann boundaries for the global problem. 413 414 Not collective 415 416 Input Parameters: 417 + pc - the preconditioning context 418 419 Output Parameters: 420 + NeumannBoundaries - index set defining the subdomain part of Neumann boundaries 421 422 Level: intermediate 423 424 Notes: 425 426 .seealso: PCBDDC 427 @*/ 428 PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries) 429 { 430 PetscErrorCode ierr; 431 432 PetscFunctionBegin; 433 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 434 ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr); 435 PetscFunctionReturn(0); 436 } 437 /* -------------------------------------------------------------------------- */ 438 439 #undef __FUNCT__ 440 #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph_BDDC" 441 static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode) 442 { 443 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 444 PCBDDCGraph mat_graph = pcbddc->mat_graph; 445 PetscErrorCode ierr; 446 447 PetscFunctionBegin; 448 /* free old CSR */ 449 ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr); 450 /* TODO: PCBDDCGraphSetAdjacency */ 451 /* get CSR into graph structure */ 452 if (copymode == PETSC_COPY_VALUES) { 453 ierr = PetscMalloc((nvtxs+1)*sizeof(PetscInt),&mat_graph->xadj);CHKERRQ(ierr); 454 ierr = PetscMalloc(xadj[nvtxs]*sizeof(PetscInt),&mat_graph->adjncy);CHKERRQ(ierr); 455 ierr = PetscMemcpy(mat_graph->xadj,xadj,(nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr); 456 ierr = PetscMemcpy(mat_graph->adjncy,adjncy,xadj[nvtxs]*sizeof(PetscInt));CHKERRQ(ierr); 457 } else if (copymode == PETSC_OWN_POINTER) { 458 mat_graph->xadj = (PetscInt*)xadj; 459 mat_graph->adjncy = (PetscInt*)adjncy; 460 } 461 mat_graph->nvtxs_csr = nvtxs; 462 PetscFunctionReturn(0); 463 } 464 465 #undef __FUNCT__ 466 #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph" 467 /*@ 468 PCBDDCSetLocalAdjacencyGraph - Set CSR graph of local matrix for use of PCBDDC. 469 470 Not collective 471 472 Input Parameters: 473 + pc - the preconditioning context 474 - nvtxs - number of local vertices of the graph 475 - xadj, adjncy - the CSR graph 476 - copymode - either PETSC_COPY_VALUES or PETSC_OWN_POINTER. In the former case the user must free the array passed in; 477 in the latter case, memory must be obtained with PetscMalloc. 478 479 Level: intermediate 480 481 Notes: 482 483 .seealso: PCBDDC 484 @*/ 485 PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode) 486 { 487 void (*f)(void) = 0; 488 PetscErrorCode ierr; 489 490 PetscFunctionBegin; 491 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 492 PetscValidIntPointer(xadj,3); 493 PetscValidIntPointer(xadj,4); 494 if (copymode != PETSC_COPY_VALUES && copymode != PETSC_OWN_POINTER) { 495 SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %d in %s\n",copymode,__FUNCT__); 496 } 497 ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr); 498 /* free arrays if PCBDDC is not the PC type */ 499 ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr); 500 if (!f && copymode == PETSC_OWN_POINTER) { 501 ierr = PetscFree(xadj);CHKERRQ(ierr); 502 ierr = PetscFree(adjncy);CHKERRQ(ierr); 503 } 504 PetscFunctionReturn(0); 505 } 506 /* -------------------------------------------------------------------------- */ 507 508 #undef __FUNCT__ 509 #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC" 510 static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[]) 511 { 512 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 513 PetscInt i; 514 PetscErrorCode ierr; 515 516 PetscFunctionBegin; 517 /* Destroy ISes if they were already set */ 518 for (i=0;i<pcbddc->n_ISForDofs;i++) { 519 ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr); 520 } 521 ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr); 522 /* allocate space then set */ 523 ierr = PetscMalloc(n_is*sizeof(IS),&pcbddc->ISForDofs);CHKERRQ(ierr); 524 for (i=0;i<n_is;i++) { 525 ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr); 526 pcbddc->ISForDofs[i]=ISForDofs[i]; 527 } 528 pcbddc->n_ISForDofs=n_is; 529 PetscFunctionReturn(0); 530 } 531 532 #undef __FUNCT__ 533 #define __FUNCT__ "PCBDDCSetDofsSplitting" 534 /*@ 535 PCBDDCSetDofsSplitting - Set index sets defining fields of local mat. 536 537 Not collective 538 539 Input Parameters: 540 + pc - the preconditioning context 541 - n - number of index sets defining the fields 542 - IS[] - array of IS describing the fields 543 544 Level: intermediate 545 546 Notes: 547 548 .seealso: PCBDDC 549 @*/ 550 PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[]) 551 { 552 PetscInt i; 553 PetscErrorCode ierr; 554 555 PetscFunctionBegin; 556 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 557 for (i=0;i<n_is;i++) { 558 PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,2); 559 } 560 ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr); 561 PetscFunctionReturn(0); 562 } 563 /* -------------------------------------------------------------------------- */ 564 #undef __FUNCT__ 565 #define __FUNCT__ "PCPreSolve_BDDC" 566 /* -------------------------------------------------------------------------- */ 567 /* 568 PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial 569 guess if a transformation of basis approach has been selected. 570 571 Input Parameter: 572 + pc - the preconditioner contex 573 574 Application Interface Routine: PCPreSolve() 575 576 Notes: 577 The interface routine PCPreSolve() is not usually called directly by 578 the user, but instead is called by KSPSolve(). 579 */ 580 static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x) 581 { 582 PetscErrorCode ierr; 583 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 584 PC_IS *pcis = (PC_IS*)(pc->data); 585 Mat_IS *matis = (Mat_IS*)pc->pmat->data; 586 Mat temp_mat; 587 IS dirIS; 588 PetscInt dirsize,i,*is_indices; 589 PetscScalar *array_x,*array_diagonal; 590 Vec used_vec; 591 PetscBool guess_nonzero; 592 593 PetscFunctionBegin; 594 /* Creates parallel work vectors used in presolve. */ 595 if (!pcbddc->original_rhs) { 596 ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr); 597 } 598 if (!pcbddc->temp_solution) { 599 ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr); 600 } 601 if (x) { 602 ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr); 603 used_vec = x; 604 } else { 605 ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr); 606 used_vec = pcbddc->temp_solution; 607 ierr = VecSet(used_vec,0.0);CHKERRQ(ierr); 608 } 609 /* hack into ksp data structure PCPreSolve comes earlier in src/ksp/ksp/interface/itfunc.c */ 610 if (ksp) { 611 ierr = KSPGetInitialGuessNonzero(ksp,&guess_nonzero);CHKERRQ(ierr); 612 if ( !guess_nonzero ) { 613 ierr = VecSet(used_vec,0.0);CHKERRQ(ierr); 614 } 615 } 616 617 if (rhs) { /* TODO: wiser handling of rhs removal, which is only needed in case of zeroed rows */ 618 /* store the original rhs */ 619 ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr); 620 621 /* Take into account zeroed rows -> change rhs and store solution removed */ 622 ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr); 623 ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr); 624 ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 625 ierr = VecScatterEnd(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 626 ierr = VecScatterBegin(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 627 ierr = VecScatterEnd(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 628 ierr = PCBDDCGetDirichletBoundaries(pc,&dirIS);CHKERRQ(ierr); 629 if (dirIS) { 630 ierr = ISGetSize(dirIS,&dirsize);CHKERRQ(ierr); 631 ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr); 632 ierr = VecGetArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr); 633 ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr); 634 for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]]; 635 ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr); 636 ierr = VecRestoreArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr); 637 ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr); 638 } 639 ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 640 ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 641 642 /* remove the computed solution from the rhs */ 643 ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr); 644 ierr = MatMultAdd(pc->pmat,used_vec,rhs,rhs);CHKERRQ(ierr); 645 ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr); 646 } 647 648 /* store partially computed solution and set initial guess */ 649 if (x) { 650 ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr); 651 ierr = VecSet(used_vec,0.0);CHKERRQ(ierr); 652 if (pcbddc->use_exact_dirichlet && !pcbddc->coarse_psi_B) { 653 ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 654 ierr = VecScatterEnd (pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 655 ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr); 656 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 657 ierr = VecScatterEnd (pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 658 if (ksp) { 659 ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr); 660 } 661 } 662 } 663 664 if (pcbddc->use_change_of_basis) { 665 /* swap pointers for local matrices */ 666 temp_mat = matis->A; 667 matis->A = pcbddc->local_mat; 668 pcbddc->local_mat = temp_mat; 669 } 670 if (pcbddc->use_change_of_basis && rhs) { 671 /* Get local rhs and apply transformation of basis */ 672 ierr = VecScatterBegin(pcis->global_to_B,rhs,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 673 ierr = VecScatterEnd (pcis->global_to_B,rhs,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 674 /* from original basis to modified basis */ 675 ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr); 676 /* put back modified values into the global vec using INSERT_VALUES copy mode */ 677 ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 678 ierr = VecScatterEnd (pcis->global_to_B,pcis->vec2_B,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 679 } 680 if (ksp && pcbddc->NullSpace) { 681 ierr = MatNullSpaceRemove(pcbddc->NullSpace,used_vec);CHKERRQ(ierr); 682 ierr = MatNullSpaceRemove(pcbddc->NullSpace,rhs);CHKERRQ(ierr); 683 } 684 ierr = VecDestroy(&used_vec);CHKERRQ(ierr); 685 PetscFunctionReturn(0); 686 } 687 /* -------------------------------------------------------------------------- */ 688 #undef __FUNCT__ 689 #define __FUNCT__ "PCPostSolve_BDDC" 690 /* -------------------------------------------------------------------------- */ 691 /* 692 PCPostSolve_BDDC - Changes the computed solution if a transformation of basis 693 approach has been selected. Also, restores rhs to its original state. 694 695 Input Parameter: 696 + pc - the preconditioner contex 697 698 Application Interface Routine: PCPostSolve() 699 700 Notes: 701 The interface routine PCPostSolve() is not usually called directly by 702 the user, but instead is called by KSPSolve(). 703 */ 704 static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x) 705 { 706 PetscErrorCode ierr; 707 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 708 PC_IS *pcis = (PC_IS*)(pc->data); 709 Mat_IS *matis = (Mat_IS*)pc->pmat->data; 710 Mat temp_mat; 711 712 PetscFunctionBegin; 713 if (pcbddc->use_change_of_basis) { 714 /* swap pointers for local matrices */ 715 temp_mat = matis->A; 716 matis->A = pcbddc->local_mat; 717 pcbddc->local_mat = temp_mat; 718 } 719 if (pcbddc->use_change_of_basis && x) { 720 /* Get Local boundary and apply transformation of basis to solution vector */ 721 ierr = VecScatterBegin(pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 722 ierr = VecScatterEnd (pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 723 /* from modified basis to original basis */ 724 ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr); 725 /* put back modified values into the global vec using INSERT_VALUES copy mode */ 726 ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 727 ierr = VecScatterEnd (pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 728 } 729 /* add solution removed in presolve */ 730 if (x) { 731 ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr); 732 } 733 /* restore rhs to its original state */ 734 if (rhs) { 735 ierr = VecCopy(pcbddc->original_rhs,rhs);CHKERRQ(ierr); 736 } 737 PetscFunctionReturn(0); 738 } 739 /* -------------------------------------------------------------------------- */ 740 #undef __FUNCT__ 741 #define __FUNCT__ "PCSetUp_BDDC" 742 /* -------------------------------------------------------------------------- */ 743 /* 744 PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner 745 by setting data structures and options. 746 747 Input Parameter: 748 + pc - the preconditioner context 749 750 Application Interface Routine: PCSetUp() 751 752 Notes: 753 The interface routine PCSetUp() is not usually called directly by 754 the user, but instead is called by PCApply() if necessary. 755 */ 756 PetscErrorCode PCSetUp_BDDC(PC pc) 757 { 758 PetscErrorCode ierr; 759 PC_BDDC* pcbddc = (PC_BDDC*)pc->data; 760 MatStructure flag; 761 PetscBool computeis,computetopography,computesolvers; 762 763 PetscFunctionBegin; 764 /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other nonoverlapping preconditioners */ 765 /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup 766 So, we set to pcnone the Neumann problem of pcis in order to avoid unneeded computation 767 Also, we decide to directly build the (same) Dirichlet problem */ 768 ierr = PetscOptionsSetValue("-is_localN_pc_type","none");CHKERRQ(ierr); 769 ierr = PetscOptionsSetValue("-is_localD_pc_type","none");CHKERRQ(ierr); 770 /* Get stdout for dbg */ 771 if (pcbddc->dbg_flag && !pcbddc->dbg_viewer) { 772 ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pc),&pcbddc->dbg_viewer);CHKERRQ(ierr); 773 ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr); 774 if (pcbddc->current_level) { 775 ierr = PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2);CHKERRQ(ierr); 776 } 777 } 778 /* first attempt to split work */ 779 if (pc->setupcalled) { 780 computeis = PETSC_FALSE; 781 ierr = PCGetOperators(pc,NULL,NULL,&flag);CHKERRQ(ierr); 782 if (flag == SAME_PRECONDITIONER) { 783 computetopography = PETSC_FALSE; 784 computesolvers = PETSC_FALSE; 785 } else if (flag == SAME_NONZERO_PATTERN) { 786 computetopography = PETSC_FALSE; 787 computesolvers = PETSC_TRUE; 788 } else { /* DIFFERENT_NONZERO_PATTERN */ 789 computetopography = PETSC_TRUE; 790 computesolvers = PETSC_TRUE; 791 } 792 } else { 793 computeis = PETSC_TRUE; 794 computetopography = PETSC_TRUE; 795 computesolvers = PETSC_TRUE; 796 } 797 /* Set up all the "iterative substructuring" common block */ 798 if (computeis) { 799 ierr = PCISSetUp(pc);CHKERRQ(ierr); 800 } 801 /* Analyze interface and set up local constraint and change of basis matrices */ 802 if (computetopography) { 803 /* reset data */ 804 ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr); 805 ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr); 806 ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr); 807 } 808 if (computesolvers) { 809 /* reset data */ 810 ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr); 811 ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr); 812 /* Create coarse and local stuffs */ 813 ierr = PCBDDCSetUpSolvers(pc);CHKERRQ(ierr); 814 ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr); 815 } 816 if (pcbddc->dbg_flag && pcbddc->current_level) { 817 ierr = PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2);CHKERRQ(ierr); 818 } 819 PetscFunctionReturn(0); 820 } 821 822 /* -------------------------------------------------------------------------- */ 823 /* 824 PCApply_BDDC - Applies the BDDC preconditioner to a vector. 825 826 Input Parameters: 827 . pc - the preconditioner context 828 . r - input vector (global) 829 830 Output Parameter: 831 . z - output vector (global) 832 833 Application Interface Routine: PCApply() 834 */ 835 #undef __FUNCT__ 836 #define __FUNCT__ "PCApply_BDDC" 837 PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z) 838 { 839 PC_IS *pcis = (PC_IS*)(pc->data); 840 PC_BDDC *pcbddc = (PC_BDDC*)(pc->data); 841 PetscErrorCode ierr; 842 const PetscScalar one = 1.0; 843 const PetscScalar m_one = -1.0; 844 const PetscScalar zero = 0.0; 845 846 /* This code is similar to that provided in nn.c for PCNN 847 NN interface preconditioner changed to BDDC 848 Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static = PETSC_TRUE) */ 849 850 PetscFunctionBegin; 851 if (!pcbddc->use_exact_dirichlet || pcbddc->coarse_psi_B) { 852 /* First Dirichlet solve */ 853 ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 854 ierr = VecScatterEnd (pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 855 ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr); 856 /* 857 Assembling right hand side for BDDC operator 858 - pcis->vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE) 859 - pcis->vec1_B the interface part of the global vector z 860 */ 861 ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr); 862 ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr); 863 if (pcbddc->switch_static) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); } 864 ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr); 865 ierr = VecCopy(r,z);CHKERRQ(ierr); 866 ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 867 ierr = VecScatterEnd (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 868 ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr); 869 } else { 870 ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr); 871 ierr = VecSet(pcis->vec2_D,zero);CHKERRQ(ierr); 872 ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr); 873 } 874 875 /* Apply interface preconditioner 876 input/output vecs: pcis->vec1_B and pcis->vec1_D */ 877 ierr = PCBDDCApplyInterfacePreconditioner(pc);CHKERRQ(ierr); 878 879 /* Apply transpose of partition of unity operator */ 880 ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr); 881 882 /* Second Dirichlet solve and assembling of output */ 883 ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 884 ierr = VecScatterEnd (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 885 ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr); 886 if (pcbddc->switch_static) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); } 887 ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcbddc->vec4_D);CHKERRQ(ierr); 888 ierr = VecScale(pcbddc->vec4_D,m_one);CHKERRQ(ierr); 889 if (pcbddc->switch_static) { ierr = VecAXPY (pcbddc->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); } 890 ierr = VecAXPY (pcis->vec2_D,one,pcbddc->vec4_D);CHKERRQ(ierr); 891 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 892 ierr = VecScatterEnd (pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 893 PetscFunctionReturn(0); 894 } 895 /* -------------------------------------------------------------------------- */ 896 897 #undef __FUNCT__ 898 #define __FUNCT__ "PCDestroy_BDDC" 899 PetscErrorCode PCDestroy_BDDC(PC pc) 900 { 901 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 902 PetscErrorCode ierr; 903 904 PetscFunctionBegin; 905 /* free data created by PCIS */ 906 ierr = PCISDestroy(pc);CHKERRQ(ierr); 907 /* free BDDC custom data */ 908 ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr); 909 /* destroy objects related to topography */ 910 ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr); 911 /* free allocated graph structure */ 912 ierr = PetscFree(pcbddc->mat_graph);CHKERRQ(ierr); 913 /* free data for scaling operator */ 914 ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr); 915 /* free solvers stuff */ 916 ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr); 917 ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr); 918 ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr); 919 ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr); 920 ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr); 921 /* free global vectors needed in presolve */ 922 ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr); 923 ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr); 924 /* remove functions */ 925 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr); 926 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr); 927 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL);CHKERRQ(ierr); 928 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL);CHKERRQ(ierr); 929 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL);CHKERRQ(ierr); 930 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",NULL);CHKERRQ(ierr); 931 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr); 932 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr); 933 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr); 934 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr); 935 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr); 936 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr); 937 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr); 938 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr); 939 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr); 940 /* Free the private data structure */ 941 ierr = PetscFree(pc->data);CHKERRQ(ierr); 942 PetscFunctionReturn(0); 943 } 944 /* -------------------------------------------------------------------------- */ 945 946 #undef __FUNCT__ 947 #define __FUNCT__ "PCBDDCMatFETIDPGetRHS_BDDC" 948 static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) 949 { 950 FETIDPMat_ctx mat_ctx; 951 PC_IS* pcis; 952 PC_BDDC* pcbddc; 953 PetscErrorCode ierr; 954 955 PetscFunctionBegin; 956 ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr); 957 pcis = (PC_IS*)mat_ctx->pc->data; 958 pcbddc = (PC_BDDC*)mat_ctx->pc->data; 959 960 /* change of basis for physical rhs if needed 961 It also changes the rhs in case of dirichlet boundaries */ 962 ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,standard_rhs,NULL);CHKERRQ(ierr); 963 /* store vectors for computation of fetidp final solution */ 964 ierr = VecScatterBegin(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 965 ierr = VecScatterEnd(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 966 /* scale rhs since it should be unassembled */ 967 /* TODO use counter scaling? (also below) */ 968 ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 969 ierr = VecScatterEnd(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 970 /* Apply partition of unity */ 971 ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr); 972 /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */ 973 if (!pcbddc->switch_static) { 974 /* compute partially subassembled Schur complement right-hand side */ 975 ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr); 976 ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr); 977 ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr); 978 ierr = VecSet(standard_rhs,0.0);CHKERRQ(ierr); 979 ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 980 ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 981 /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */ 982 ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 983 ierr = VecScatterEnd(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 984 ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr); 985 } 986 /* BDDC rhs */ 987 ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr); 988 if (pcbddc->switch_static) { 989 ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr); 990 } 991 /* apply BDDC */ 992 ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc);CHKERRQ(ierr); 993 /* Application of B_delta and assembling of rhs for fetidp fluxes */ 994 ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr); 995 ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr); 996 ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 997 ierr = VecScatterEnd (mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 998 /* restore original rhs */ 999 ierr = VecCopy(pcbddc->original_rhs,standard_rhs);CHKERRQ(ierr); 1000 PetscFunctionReturn(0); 1001 } 1002 1003 #undef __FUNCT__ 1004 #define __FUNCT__ "PCBDDCMatFETIDPGetRHS" 1005 /*@ 1006 PCBDDCMatFETIDPGetRHS - Get rhs for FETIDP linear system. 1007 1008 Collective 1009 1010 Input Parameters: 1011 + fetidp_mat - the FETIDP mat obtained by a call to PCBDDCCreateFETIDPOperators 1012 + standard_rhs - the rhs of your linear system 1013 1014 Output Parameters: 1015 + fetidp_flux_rhs - the rhs of the FETIDP linear system 1016 1017 Level: developer 1018 1019 Notes: 1020 1021 .seealso: PCBDDC 1022 @*/ 1023 PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) 1024 { 1025 FETIDPMat_ctx mat_ctx; 1026 PetscErrorCode ierr; 1027 1028 PetscFunctionBegin; 1029 ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr); 1030 ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr); 1031 PetscFunctionReturn(0); 1032 } 1033 /* -------------------------------------------------------------------------- */ 1034 1035 #undef __FUNCT__ 1036 #define __FUNCT__ "PCBDDCMatFETIDPGetSolution_BDDC" 1037 static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) 1038 { 1039 FETIDPMat_ctx mat_ctx; 1040 PC_IS* pcis; 1041 PC_BDDC* pcbddc; 1042 PetscErrorCode ierr; 1043 1044 PetscFunctionBegin; 1045 ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr); 1046 pcis = (PC_IS*)mat_ctx->pc->data; 1047 pcbddc = (PC_BDDC*)mat_ctx->pc->data; 1048 1049 /* apply B_delta^T */ 1050 ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1051 ierr = VecScatterEnd (mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1052 ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr); 1053 /* compute rhs for BDDC application */ 1054 ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr); 1055 if (pcbddc->switch_static) { 1056 ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr); 1057 } 1058 /* apply BDDC */ 1059 ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc);CHKERRQ(ierr); 1060 /* put values into standard global vector */ 1061 ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1062 ierr = VecScatterEnd (pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1063 if (!pcbddc->switch_static) { 1064 /* compute values into the interior if solved for the partially subassembled Schur complement */ 1065 ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr); 1066 ierr = VecAXPY(mat_ctx->temp_solution_D,-1.0,pcis->vec1_D);CHKERRQ(ierr); 1067 ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr); 1068 } 1069 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1070 ierr = VecScatterEnd (pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1071 /* final change of basis if needed 1072 Is also sums the dirichlet part removed during RHS assembling */ 1073 ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr); 1074 PetscFunctionReturn(0); 1075 } 1076 1077 #undef __FUNCT__ 1078 #define __FUNCT__ "PCBDDCMatFETIDPGetSolution" 1079 /*@ 1080 PCBDDCMatFETIDPGetSolution - Get Solution for FETIDP linear system. 1081 1082 Collective 1083 1084 Input Parameters: 1085 + fetidp_mat - the FETIDP mat obtained by a call to PCBDDCCreateFETIDPOperators 1086 + fetidp_flux_sol - the solution of the FETIDP linear system 1087 1088 Output Parameters: 1089 + standard_sol - the solution on the global domain 1090 1091 Level: developer 1092 1093 Notes: 1094 1095 .seealso: PCBDDC 1096 @*/ 1097 PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) 1098 { 1099 FETIDPMat_ctx mat_ctx; 1100 PetscErrorCode ierr; 1101 1102 PetscFunctionBegin; 1103 ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr); 1104 ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr); 1105 PetscFunctionReturn(0); 1106 } 1107 /* -------------------------------------------------------------------------- */ 1108 1109 extern PetscErrorCode FETIDPMatMult(Mat,Vec,Vec); 1110 extern PetscErrorCode PCBDDCDestroyFETIDPMat(Mat); 1111 extern PetscErrorCode FETIDPPCApply(PC,Vec,Vec); 1112 extern PetscErrorCode PCBDDCDestroyFETIDPPC(PC); 1113 1114 #undef __FUNCT__ 1115 #define __FUNCT__ "PCBDDCCreateFETIDPOperators_BDDC" 1116 static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, Mat *fetidp_mat, PC *fetidp_pc) 1117 { 1118 1119 FETIDPMat_ctx fetidpmat_ctx; 1120 Mat newmat; 1121 FETIDPPC_ctx fetidppc_ctx; 1122 PC newpc; 1123 MPI_Comm comm; 1124 PetscErrorCode ierr; 1125 1126 PetscFunctionBegin; 1127 ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr); 1128 /* FETIDP linear matrix */ 1129 ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr); 1130 ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr); 1131 ierr = MatCreateShell(comm,PETSC_DECIDE,PETSC_DECIDE,fetidpmat_ctx->n_lambda,fetidpmat_ctx->n_lambda,fetidpmat_ctx,&newmat);CHKERRQ(ierr); 1132 ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr); 1133 ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr); 1134 ierr = MatSetUp(newmat);CHKERRQ(ierr); 1135 /* FETIDP preconditioner */ 1136 ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr); 1137 ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr); 1138 ierr = PCCreate(comm,&newpc);CHKERRQ(ierr); 1139 ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr); 1140 ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr); 1141 ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr); 1142 ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr); 1143 ierr = PCSetOperators(newpc,newmat,newmat,SAME_PRECONDITIONER);CHKERRQ(ierr); 1144 ierr = PCSetUp(newpc);CHKERRQ(ierr); 1145 /* return pointers for objects created */ 1146 *fetidp_mat=newmat; 1147 *fetidp_pc=newpc; 1148 PetscFunctionReturn(0); 1149 } 1150 1151 #undef __FUNCT__ 1152 #define __FUNCT__ "PCBDDCCreateFETIDPOperators" 1153 /*@ 1154 PCBDDCCreateFETIDPOperators - Create operators for FETIDP. 1155 1156 Collective 1157 1158 Input Parameters: 1159 + pc - the BDDC preconditioning context (setup must be already called) 1160 1161 Level: developer 1162 1163 Notes: 1164 1165 .seealso: PCBDDC 1166 @*/ 1167 PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, Mat *fetidp_mat, PC *fetidp_pc) 1168 { 1169 PetscErrorCode ierr; 1170 1171 PetscFunctionBegin; 1172 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1173 if (pc->setupcalled) { 1174 ierr = PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,Mat*,PC*),(pc,fetidp_mat,fetidp_pc));CHKERRQ(ierr); 1175 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"You must call PCSetup_BDDC() first \n"); 1176 PetscFunctionReturn(0); 1177 } 1178 /* -------------------------------------------------------------------------- */ 1179 /*MC 1180 PCBDDC - Balancing Domain Decomposition by Constraints. 1181 1182 Options Database Keys: 1183 . -pcbddc ??? - 1184 1185 Level: intermediate 1186 1187 Notes: The matrix used with this preconditioner must be of type MATIS 1188 1189 Unlike more 'conventional' interface preconditioners, this iterates over ALL the 1190 degrees of freedom, NOT just those on the interface (this allows the use of approximate solvers 1191 on the subdomains). 1192 1193 Options for the coarse grid preconditioner can be set with - 1194 Options for the Dirichlet subproblem can be set with - 1195 Options for the Neumann subproblem can be set with - 1196 1197 Contributed by Stefano Zampini 1198 1199 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, MATIS 1200 M*/ 1201 1202 #undef __FUNCT__ 1203 #define __FUNCT__ "PCCreate_BDDC" 1204 PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc) 1205 { 1206 PetscErrorCode ierr; 1207 PC_BDDC *pcbddc; 1208 1209 PetscFunctionBegin; 1210 /* Creates the private data structure for this preconditioner and attach it to the PC object. */ 1211 ierr = PetscNewLog(pc,PC_BDDC,&pcbddc);CHKERRQ(ierr); 1212 pc->data = (void*)pcbddc; 1213 1214 /* create PCIS data structure */ 1215 ierr = PCISCreate(pc);CHKERRQ(ierr); 1216 1217 /* BDDC customization */ 1218 pcbddc->use_vertices = PETSC_TRUE; 1219 pcbddc->use_edges = PETSC_TRUE; 1220 pcbddc->use_faces = PETSC_FALSE; 1221 pcbddc->use_change_of_basis = PETSC_FALSE; 1222 pcbddc->use_change_on_faces = PETSC_FALSE; 1223 pcbddc->switch_static = PETSC_FALSE; 1224 pcbddc->use_nnsp_true = PETSC_FALSE; /* not yet exposed */ 1225 pcbddc->dbg_flag = 0; 1226 1227 pcbddc->user_primal_vertices = 0; 1228 pcbddc->NullSpace = 0; 1229 pcbddc->temp_solution = 0; 1230 pcbddc->original_rhs = 0; 1231 pcbddc->local_mat = 0; 1232 pcbddc->ChangeOfBasisMatrix = 0; 1233 pcbddc->coarse_vec = 0; 1234 pcbddc->coarse_rhs = 0; 1235 pcbddc->coarse_ksp = 0; 1236 pcbddc->coarse_phi_B = 0; 1237 pcbddc->coarse_phi_D = 0; 1238 pcbddc->coarse_psi_B = 0; 1239 pcbddc->coarse_psi_D = 0; 1240 pcbddc->vec1_P = 0; 1241 pcbddc->vec1_R = 0; 1242 pcbddc->vec2_R = 0; 1243 pcbddc->local_auxmat1 = 0; 1244 pcbddc->local_auxmat2 = 0; 1245 pcbddc->R_to_B = 0; 1246 pcbddc->R_to_D = 0; 1247 pcbddc->ksp_D = 0; 1248 pcbddc->ksp_R = 0; 1249 pcbddc->NeumannBoundaries = 0; 1250 pcbddc->ISForDofs = 0; 1251 pcbddc->ConstraintMatrix = 0; 1252 pcbddc->use_exact_dirichlet = PETSC_TRUE; 1253 pcbddc->coarse_loc_to_glob = 0; 1254 pcbddc->coarsening_ratio = 8; 1255 pcbddc->current_level = 0; 1256 pcbddc->max_levels = 0; 1257 1258 /* create local graph structure */ 1259 ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr); 1260 1261 /* scaling */ 1262 pcbddc->use_deluxe_scaling = PETSC_FALSE; 1263 pcbddc->work_scaling = 0; 1264 1265 /* function pointers */ 1266 pc->ops->apply = PCApply_BDDC; 1267 pc->ops->applytranspose = 0; 1268 pc->ops->setup = PCSetUp_BDDC; 1269 pc->ops->destroy = PCDestroy_BDDC; 1270 pc->ops->setfromoptions = PCSetFromOptions_BDDC; 1271 pc->ops->view = 0; 1272 pc->ops->applyrichardson = 0; 1273 pc->ops->applysymmetricleft = 0; 1274 pc->ops->applysymmetricright = 0; 1275 pc->ops->presolve = PCPreSolve_BDDC; 1276 pc->ops->postsolve = PCPostSolve_BDDC; 1277 1278 /* composing function */ 1279 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr); 1280 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr); 1281 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC);CHKERRQ(ierr); 1282 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC);CHKERRQ(ierr); 1283 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC);CHKERRQ(ierr); 1284 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",PCBDDCSetNullSpace_BDDC);CHKERRQ(ierr); 1285 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr); 1286 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr); 1287 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr); 1288 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr); 1289 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr); 1290 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr); 1291 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr); 1292 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr); 1293 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr); 1294 PetscFunctionReturn(0); 1295 } 1296 1297