1 /* TODOLIST 2 3 ConstraintsSetup 4 - tolerances for constraints as an option (take care of single precision!) 5 6 Solvers 7 - Add support for cholesky for coarse solver (similar to local solvers) 8 - Propagate ksp prefixes for solvers to mat objects? 9 - Propagate nearnullspace info among levels 10 11 User interface 12 - ** DofSplitting and DM attached to pc? 13 14 Debugging output 15 - * Better management of verbosity levels of debugging output 16 17 Build 18 - make runexe59 19 20 Extra 21 - ** GetRid of PCBDDCApplySchur, use MatSchur instead 22 - *** Is it possible to work with PCBDDCGraph on boundary indices only (less memory consumed)? 23 - add support for computing h,H and related using coordinates? 24 - Change of basis approach does not work with my nonlinear mechanics example. why? (seems not an issue with l2gmap) 25 - Better management in PCIS code 26 - BDDC with MG framework? 27 28 FETIDP 29 - Move FETIDP code to its own classes 30 31 MATIS related operations contained in BDDC code 32 - Provide general case for subassembling 33 - *** Preallocation routines in MatISGetMPIAXAIJ 34 35 */ 36 37 /* ---------------------------------------------------------------------------------------------------------------------------------------------- 38 Implementation of BDDC preconditioner based on: 39 C. Dohrmann "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007 40 ---------------------------------------------------------------------------------------------------------------------------------------------- */ 41 42 #include <../src/ksp/pc/impls/bddc/bddc.h> /*I "petscpc.h" I*/ /* includes for fortran wrappers */ 43 #include <../src/ksp/pc/impls/bddc/bddcprivate.h> 44 #include <petscblaslapack.h> 45 46 /* -------------------------------------------------------------------------- */ 47 #undef __FUNCT__ 48 #define __FUNCT__ "PCSetFromOptions_BDDC" 49 PetscErrorCode PCSetFromOptions_BDDC(PC pc) 50 { 51 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 52 PetscErrorCode ierr; 53 54 PetscFunctionBegin; 55 ierr = PetscOptionsHead("BDDC options");CHKERRQ(ierr); 56 /* Verbose debugging */ 57 ierr = PetscOptionsInt("-pc_bddc_check_level","Verbose output for PCBDDC (intended for debug)","none",pcbddc->dbg_flag,&pcbddc->dbg_flag,NULL);CHKERRQ(ierr); 58 /* Primal space cumstomization */ 59 ierr = PetscOptionsBool("-pc_bddc_use_local_mat_graph","Use or not adjacency graph of local mat for interface analysis","none",pcbddc->use_local_adj,&pcbddc->use_local_adj,NULL);CHKERRQ(ierr); 60 ierr = PetscOptionsBool("-pc_bddc_use_vertices","Use or not corner dofs in coarse space","none",pcbddc->use_vertices,&pcbddc->use_vertices,NULL);CHKERRQ(ierr); 61 ierr = PetscOptionsBool("-pc_bddc_use_edges","Use or not edge constraints in coarse space","none",pcbddc->use_edges,&pcbddc->use_edges,NULL);CHKERRQ(ierr); 62 ierr = PetscOptionsBool("-pc_bddc_use_faces","Use or not face constraints in coarse space","none",pcbddc->use_faces,&pcbddc->use_faces,NULL);CHKERRQ(ierr); 63 /* Change of basis */ 64 ierr = PetscOptionsBool("-pc_bddc_use_change_of_basis","Use or not internal change of basis on local edge nodes","none",pcbddc->use_change_of_basis,&pcbddc->use_change_of_basis,NULL);CHKERRQ(ierr); 65 ierr = PetscOptionsBool("-pc_bddc_use_change_on_faces","Use or not internal change of basis on local face nodes","none",pcbddc->use_change_on_faces,&pcbddc->use_change_on_faces,NULL);CHKERRQ(ierr); 66 if (!pcbddc->use_change_of_basis) { 67 pcbddc->use_change_on_faces = PETSC_FALSE; 68 } 69 /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */ 70 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); 71 ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","none",pcbddc->coarsening_ratio,&pcbddc->coarsening_ratio,NULL);CHKERRQ(ierr); 72 ierr = PetscOptionsInt("-pc_bddc_levels","Set maximum number of levels for multilevel","none",pcbddc->max_levels,&pcbddc->max_levels,NULL);CHKERRQ(ierr); 73 ierr = PetscOptionsBool("-pc_bddc_use_coarse_estimates","Use estimated eigenvalues for coarse problem","none",pcbddc->use_coarse_estimates,&pcbddc->use_coarse_estimates,NULL);CHKERRQ(ierr); 74 ierr = PetscOptionsBool("-pc_bddc_use_deluxe_scaling","Use deluxe scaling for BDDC","none",pcbddc->use_deluxe_scaling,&pcbddc->use_deluxe_scaling,NULL);CHKERRQ(ierr); 75 ierr = PetscOptionsInt("-pc_bddc_deluxe_threshold","Deluxe subproblems (Schur principal minors) smaller than this value are explicilty computed (-1 computes all)","none",pcbddc->deluxe_threshold,&pcbddc->deluxe_threshold,NULL);CHKERRQ(ierr); 76 ierr = PetscOptionsBool("-pc_bddc_deluxe_rebuild","Whether or not the interface graph for deluxe has to be rebuilt (i.e. use a standard definition of the interface)","none",pcbddc->deluxe_rebuild,&pcbddc->deluxe_rebuild,NULL);CHKERRQ(ierr); 77 ierr = PetscOptionsInt("-pc_bddc_deluxe_layers","Number of dofs' layers for the application of deluxe cheap version (i.e. -1 uses all dofs)","none",pcbddc->deluxe_layers,&pcbddc->deluxe_layers,NULL);CHKERRQ(ierr); 78 ierr = PetscOptionsBool("-pc_bddc_deluxe_use_useradj","Whether or not the CSR graph specified by the user should be used for computing layers (default is to use adj of local mat)","none",pcbddc->deluxe_use_useradj,&pcbddc->deluxe_use_useradj,NULL);CHKERRQ(ierr); 79 ierr = PetscOptionsTail();CHKERRQ(ierr); 80 PetscFunctionReturn(0); 81 } 82 /* -------------------------------------------------------------------------- */ 83 #undef __FUNCT__ 84 #define __FUNCT__ "PCBDDCSetChangeOfBasisMat_BDDC" 85 static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change) 86 { 87 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 88 PetscErrorCode ierr; 89 90 PetscFunctionBegin; 91 ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr); 92 ierr = PetscObjectReference((PetscObject)change);CHKERRQ(ierr); 93 pcbddc->user_ChangeOfBasisMatrix = change; 94 PetscFunctionReturn(0); 95 } 96 #undef __FUNCT__ 97 #define __FUNCT__ "PCBDDCSetChangeOfBasisMat" 98 /*@ 99 PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs 100 101 Collective on PC 102 103 Input Parameters: 104 + pc - the preconditioning context 105 - change - the change of basis matrix 106 107 Level: intermediate 108 109 Notes: 110 111 .seealso: PCBDDC 112 @*/ 113 PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change) 114 { 115 PetscErrorCode ierr; 116 117 PetscFunctionBegin; 118 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 119 PetscValidHeaderSpecific(change,MAT_CLASSID,2); 120 PetscCheckSameComm(pc,1,change,2); 121 if (pc->mat) { 122 PetscInt rows_c,cols_c,rows,cols; 123 ierr = MatGetSize(pc->mat,&rows,&cols);CHKERRQ(ierr); 124 ierr = MatGetSize(change,&rows_c,&cols_c);CHKERRQ(ierr); 125 if (rows_c != rows) { 126 SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of rows for change of basis matrix! %d != %d",rows_c,rows); 127 } 128 if (cols_c != cols) { 129 SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of columns for change of basis matrix! %d != %d",cols_c,cols); 130 } 131 ierr = MatGetLocalSize(pc->mat,&rows,&cols);CHKERRQ(ierr); 132 ierr = MatGetLocalSize(change,&rows_c,&cols_c);CHKERRQ(ierr); 133 if (rows_c != rows) { 134 SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of local rows for change of basis matrix! %d != %d",rows_c,rows); 135 } 136 if (cols_c != cols) { 137 SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of local columns for change of basis matrix! %d != %d",cols_c,cols); 138 } 139 } 140 ierr = PetscTryMethod(pc,"PCBDDCSetChangeOfBasisMat_C",(PC,Mat),(pc,change));CHKERRQ(ierr); 141 PetscFunctionReturn(0); 142 } 143 /* -------------------------------------------------------------------------- */ 144 #undef __FUNCT__ 145 #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS_BDDC" 146 static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices) 147 { 148 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 149 PetscErrorCode ierr; 150 151 PetscFunctionBegin; 152 ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr); 153 ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr); 154 pcbddc->user_primal_vertices = PrimalVertices; 155 PetscFunctionReturn(0); 156 } 157 #undef __FUNCT__ 158 #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS" 159 /*@ 160 PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in PCBDDC 161 162 Not collective 163 164 Input Parameters: 165 + pc - the preconditioning context 166 - PrimalVertices - index set of primal vertices in local numbering 167 168 Level: intermediate 169 170 Notes: 171 172 .seealso: PCBDDC 173 @*/ 174 PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices) 175 { 176 PetscErrorCode ierr; 177 178 PetscFunctionBegin; 179 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 180 PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2); 181 ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr); 182 PetscFunctionReturn(0); 183 } 184 /* -------------------------------------------------------------------------- */ 185 #undef __FUNCT__ 186 #define __FUNCT__ "PCBDDCSetCoarseningRatio_BDDC" 187 static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k) 188 { 189 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 190 191 PetscFunctionBegin; 192 pcbddc->coarsening_ratio = k; 193 PetscFunctionReturn(0); 194 } 195 196 #undef __FUNCT__ 197 #define __FUNCT__ "PCBDDCSetCoarseningRatio" 198 /*@ 199 PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel 200 201 Logically collective on PC 202 203 Input Parameters: 204 + pc - the preconditioning context 205 - k - coarsening ratio (H/h at the coarser level) 206 207 Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level 208 209 Level: intermediate 210 211 Notes: 212 213 .seealso: PCBDDC 214 @*/ 215 PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k) 216 { 217 PetscErrorCode ierr; 218 219 PetscFunctionBegin; 220 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 221 PetscValidLogicalCollectiveInt(pc,k,2); 222 ierr = PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));CHKERRQ(ierr); 223 PetscFunctionReturn(0); 224 } 225 226 /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */ 227 #undef __FUNCT__ 228 #define __FUNCT__ "PCBDDCSetUseExactDirichlet_BDDC" 229 static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc,PetscBool flg) 230 { 231 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 232 233 PetscFunctionBegin; 234 pcbddc->use_exact_dirichlet_trick = flg; 235 PetscFunctionReturn(0); 236 } 237 238 #undef __FUNCT__ 239 #define __FUNCT__ "PCBDDCSetUseExactDirichlet" 240 PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool flg) 241 { 242 PetscErrorCode ierr; 243 244 PetscFunctionBegin; 245 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 246 PetscValidLogicalCollectiveBool(pc,flg,2); 247 ierr = PetscTryMethod(pc,"PCBDDCSetUseExactDirichlet_C",(PC,PetscBool),(pc,flg));CHKERRQ(ierr); 248 PetscFunctionReturn(0); 249 } 250 251 #undef __FUNCT__ 252 #define __FUNCT__ "PCBDDCSetLevel_BDDC" 253 static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc,PetscInt level) 254 { 255 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 256 257 PetscFunctionBegin; 258 pcbddc->current_level = level; 259 PetscFunctionReturn(0); 260 } 261 262 #undef __FUNCT__ 263 #define __FUNCT__ "PCBDDCSetLevel" 264 PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level) 265 { 266 PetscErrorCode ierr; 267 268 PetscFunctionBegin; 269 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 270 PetscValidLogicalCollectiveInt(pc,level,2); 271 ierr = PetscTryMethod(pc,"PCBDDCSetLevel_C",(PC,PetscInt),(pc,level));CHKERRQ(ierr); 272 PetscFunctionReturn(0); 273 } 274 275 #undef __FUNCT__ 276 #define __FUNCT__ "PCBDDCSetLevels_BDDC" 277 static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc,PetscInt levels) 278 { 279 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 280 281 PetscFunctionBegin; 282 pcbddc->max_levels = levels; 283 PetscFunctionReturn(0); 284 } 285 286 #undef __FUNCT__ 287 #define __FUNCT__ "PCBDDCSetLevels" 288 /*@ 289 PCBDDCSetLevels - Sets the maximum number of levels for multilevel 290 291 Logically collective on PC 292 293 Input Parameters: 294 + pc - the preconditioning context 295 - levels - the maximum number of levels (max 9) 296 297 Default value is 0, i.e. traditional one-level BDDC 298 299 Level: intermediate 300 301 Notes: 302 303 .seealso: PCBDDC 304 @*/ 305 PetscErrorCode PCBDDCSetLevels(PC pc,PetscInt levels) 306 { 307 PetscErrorCode ierr; 308 309 PetscFunctionBegin; 310 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 311 PetscValidLogicalCollectiveInt(pc,levels,2); 312 if (levels > 99) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Maximum number of levels for bddc is 99\n"); 313 ierr = PetscTryMethod(pc,"PCBDDCSetLevels_C",(PC,PetscInt),(pc,levels));CHKERRQ(ierr); 314 PetscFunctionReturn(0); 315 } 316 /* -------------------------------------------------------------------------- */ 317 318 #undef __FUNCT__ 319 #define __FUNCT__ "PCBDDCSetNullSpace_BDDC" 320 static PetscErrorCode PCBDDCSetNullSpace_BDDC(PC pc,MatNullSpace NullSpace) 321 { 322 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 323 PetscErrorCode ierr; 324 325 PetscFunctionBegin; 326 ierr = PetscObjectReference((PetscObject)NullSpace);CHKERRQ(ierr); 327 ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr); 328 pcbddc->NullSpace = NullSpace; 329 PetscFunctionReturn(0); 330 } 331 332 #undef __FUNCT__ 333 #define __FUNCT__ "PCBDDCSetNullSpace" 334 /*@ 335 PCBDDCSetNullSpace - Set nullspace for BDDC operator 336 337 Logically collective on PC and MatNullSpace 338 339 Input Parameters: 340 + pc - the preconditioning context 341 - NullSpace - Null space of the linear operator to be preconditioned (Pmat) 342 343 Level: intermediate 344 345 Notes: 346 347 .seealso: PCBDDC 348 @*/ 349 PetscErrorCode PCBDDCSetNullSpace(PC pc,MatNullSpace NullSpace) 350 { 351 PetscErrorCode ierr; 352 353 PetscFunctionBegin; 354 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 355 PetscValidHeaderSpecific(NullSpace,MAT_NULLSPACE_CLASSID,2); 356 PetscCheckSameComm(pc,1,NullSpace,2); 357 ierr = PetscTryMethod(pc,"PCBDDCSetNullSpace_C",(PC,MatNullSpace),(pc,NullSpace));CHKERRQ(ierr); 358 PetscFunctionReturn(0); 359 } 360 /* -------------------------------------------------------------------------- */ 361 362 #undef __FUNCT__ 363 #define __FUNCT__ "PCBDDCSetDirichletBoundaries_BDDC" 364 static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries) 365 { 366 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 367 PetscErrorCode ierr; 368 369 PetscFunctionBegin; 370 /* last user setting takes precendence -> destroy any other customization */ 371 ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr); 372 ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr); 373 ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr); 374 pcbddc->DirichletBoundaries = DirichletBoundaries; 375 pcbddc->recompute_topography = PETSC_TRUE; 376 PetscFunctionReturn(0); 377 } 378 379 #undef __FUNCT__ 380 #define __FUNCT__ "PCBDDCSetDirichletBoundaries" 381 /*@ 382 PCBDDCSetDirichletBoundaries - Set IS defining Dirichlet boundaries for the global problem. 383 384 Collective 385 386 Input Parameters: 387 + pc - the preconditioning context 388 - DirichletBoundaries - parallel IS defining the Dirichlet boundaries 389 390 Level: intermediate 391 392 Notes: Any process can list any global node 393 394 .seealso: PCBDDC 395 @*/ 396 PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries) 397 { 398 PetscErrorCode ierr; 399 400 PetscFunctionBegin; 401 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 402 PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2); 403 PetscCheckSameComm(pc,1,DirichletBoundaries,2); 404 ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr); 405 PetscFunctionReturn(0); 406 } 407 /* -------------------------------------------------------------------------- */ 408 409 #undef __FUNCT__ 410 #define __FUNCT__ "PCBDDCSetDirichletBoundariesLocal_BDDC" 411 static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc,IS DirichletBoundaries) 412 { 413 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 414 PetscErrorCode ierr; 415 416 PetscFunctionBegin; 417 /* last user setting takes precendence -> destroy any other customization */ 418 ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr); 419 ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr); 420 ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr); 421 pcbddc->DirichletBoundariesLocal = DirichletBoundaries; 422 pcbddc->recompute_topography = PETSC_TRUE; 423 PetscFunctionReturn(0); 424 } 425 426 #undef __FUNCT__ 427 #define __FUNCT__ "PCBDDCSetDirichletBoundariesLocal" 428 /*@ 429 PCBDDCSetDirichletBoundariesLocal - Set IS defining Dirichlet boundaries for the global problem in local ordering. 430 431 Collective 432 433 Input Parameters: 434 + pc - the preconditioning context 435 - DirichletBoundaries - parallel IS defining the Dirichlet boundaries (in local ordering) 436 437 Level: intermediate 438 439 Notes: 440 441 .seealso: PCBDDC 442 @*/ 443 PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc,IS DirichletBoundaries) 444 { 445 PetscErrorCode ierr; 446 447 PetscFunctionBegin; 448 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 449 PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2); 450 PetscCheckSameComm(pc,1,DirichletBoundaries,2); 451 ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundariesLocal_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr); 452 PetscFunctionReturn(0); 453 } 454 /* -------------------------------------------------------------------------- */ 455 456 #undef __FUNCT__ 457 #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC" 458 static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries) 459 { 460 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 461 PetscErrorCode ierr; 462 463 PetscFunctionBegin; 464 /* last user setting takes precendence -> destroy any other customization */ 465 ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr); 466 ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr); 467 ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr); 468 pcbddc->NeumannBoundaries = NeumannBoundaries; 469 pcbddc->recompute_topography = PETSC_TRUE; 470 PetscFunctionReturn(0); 471 } 472 473 #undef __FUNCT__ 474 #define __FUNCT__ "PCBDDCSetNeumannBoundaries" 475 /*@ 476 PCBDDCSetNeumannBoundaries - Set IS defining Neumann boundaries for the global problem. 477 478 Collective 479 480 Input Parameters: 481 + pc - the preconditioning context 482 - NeumannBoundaries - parallel IS defining the Neumann boundaries 483 484 Level: intermediate 485 486 Notes: Any process can list any global node 487 488 .seealso: PCBDDC 489 @*/ 490 PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries) 491 { 492 PetscErrorCode ierr; 493 494 PetscFunctionBegin; 495 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 496 PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2); 497 PetscCheckSameComm(pc,1,NeumannBoundaries,2); 498 ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr); 499 PetscFunctionReturn(0); 500 } 501 /* -------------------------------------------------------------------------- */ 502 503 #undef __FUNCT__ 504 #define __FUNCT__ "PCBDDCSetNeumannBoundariesLocal_BDDC" 505 static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc,IS NeumannBoundaries) 506 { 507 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 508 PetscErrorCode ierr; 509 510 PetscFunctionBegin; 511 /* last user setting takes precendence -> destroy any other customization */ 512 ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr); 513 ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr); 514 ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr); 515 pcbddc->NeumannBoundariesLocal = NeumannBoundaries; 516 pcbddc->recompute_topography = PETSC_TRUE; 517 PetscFunctionReturn(0); 518 } 519 520 #undef __FUNCT__ 521 #define __FUNCT__ "PCBDDCSetNeumannBoundariesLocal" 522 /*@ 523 PCBDDCSetNeumannBoundariesLocal - Set IS defining Neumann boundaries for the global problem in local ordering. 524 525 Collective 526 527 Input Parameters: 528 + pc - the preconditioning context 529 - NeumannBoundaries - parallel IS defining the subdomain part of Neumann boundaries (in local ordering) 530 531 Level: intermediate 532 533 Notes: 534 535 .seealso: PCBDDC 536 @*/ 537 PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc,IS NeumannBoundaries) 538 { 539 PetscErrorCode ierr; 540 541 PetscFunctionBegin; 542 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 543 PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2); 544 PetscCheckSameComm(pc,1,NeumannBoundaries,2); 545 ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundariesLocal_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr); 546 PetscFunctionReturn(0); 547 } 548 /* -------------------------------------------------------------------------- */ 549 550 #undef __FUNCT__ 551 #define __FUNCT__ "PCBDDCGetDirichletBoundaries_BDDC" 552 static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries) 553 { 554 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 555 556 PetscFunctionBegin; 557 *DirichletBoundaries = pcbddc->DirichletBoundaries; 558 PetscFunctionReturn(0); 559 } 560 561 #undef __FUNCT__ 562 #define __FUNCT__ "PCBDDCGetDirichletBoundaries" 563 /*@ 564 PCBDDCGetDirichletBoundaries - Get parallel IS for Dirichlet boundaries 565 566 Collective 567 568 Input Parameters: 569 . pc - the preconditioning context 570 571 Output Parameters: 572 . DirichletBoundaries - index set defining the Dirichlet boundaries 573 574 Level: intermediate 575 576 Notes: The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetDirichletBoundaries 577 578 .seealso: PCBDDC 579 @*/ 580 PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries) 581 { 582 PetscErrorCode ierr; 583 584 PetscFunctionBegin; 585 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 586 ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr); 587 PetscFunctionReturn(0); 588 } 589 /* -------------------------------------------------------------------------- */ 590 591 #undef __FUNCT__ 592 #define __FUNCT__ "PCBDDCGetDirichletBoundariesLocal_BDDC" 593 static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc,IS *DirichletBoundaries) 594 { 595 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 596 597 PetscFunctionBegin; 598 *DirichletBoundaries = pcbddc->DirichletBoundariesLocal; 599 PetscFunctionReturn(0); 600 } 601 602 #undef __FUNCT__ 603 #define __FUNCT__ "PCBDDCGetDirichletBoundariesLocal" 604 /*@ 605 PCBDDCGetDirichletBoundariesLocal - Get parallel IS for Dirichlet boundaries (in local ordering) 606 607 Collective 608 609 Input Parameters: 610 . pc - the preconditioning context 611 612 Output Parameters: 613 . DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries 614 615 Level: intermediate 616 617 Notes: 618 619 .seealso: PCBDDC 620 @*/ 621 PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc,IS *DirichletBoundaries) 622 { 623 PetscErrorCode ierr; 624 625 PetscFunctionBegin; 626 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 627 ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundariesLocal_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr); 628 PetscFunctionReturn(0); 629 } 630 /* -------------------------------------------------------------------------- */ 631 632 #undef __FUNCT__ 633 #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC" 634 static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries) 635 { 636 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 637 638 PetscFunctionBegin; 639 *NeumannBoundaries = pcbddc->NeumannBoundaries; 640 PetscFunctionReturn(0); 641 } 642 643 #undef __FUNCT__ 644 #define __FUNCT__ "PCBDDCGetNeumannBoundaries" 645 /*@ 646 PCBDDCGetNeumannBoundaries - Get parallel IS for Neumann boundaries 647 648 Collective 649 650 Input Parameters: 651 . pc - the preconditioning context 652 653 Output Parameters: 654 . NeumannBoundaries - index set defining the Neumann boundaries 655 656 Level: intermediate 657 658 Notes: The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetNeumannBoundaries 659 660 .seealso: PCBDDC 661 @*/ 662 PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries) 663 { 664 PetscErrorCode ierr; 665 666 PetscFunctionBegin; 667 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 668 ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr); 669 PetscFunctionReturn(0); 670 } 671 /* -------------------------------------------------------------------------- */ 672 673 #undef __FUNCT__ 674 #define __FUNCT__ "PCBDDCGetNeumannBoundariesLocal_BDDC" 675 static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc,IS *NeumannBoundaries) 676 { 677 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 678 679 PetscFunctionBegin; 680 *NeumannBoundaries = pcbddc->NeumannBoundariesLocal; 681 PetscFunctionReturn(0); 682 } 683 684 #undef __FUNCT__ 685 #define __FUNCT__ "PCBDDCGetNeumannBoundariesLocal" 686 /*@ 687 PCBDDCGetNeumannBoundariesLocal - Get parallel IS for Neumann boundaries (in local ordering) 688 689 Collective 690 691 Input Parameters: 692 . pc - the preconditioning context 693 694 Output Parameters: 695 . NeumannBoundaries - index set defining the subdomain part of Neumann boundaries 696 697 Level: intermediate 698 699 Notes: 700 701 .seealso: PCBDDC 702 @*/ 703 PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc,IS *NeumannBoundaries) 704 { 705 PetscErrorCode ierr; 706 707 PetscFunctionBegin; 708 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 709 ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundariesLocal_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr); 710 PetscFunctionReturn(0); 711 } 712 /* -------------------------------------------------------------------------- */ 713 714 #undef __FUNCT__ 715 #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph_BDDC" 716 static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode) 717 { 718 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 719 PCBDDCGraph mat_graph = pcbddc->mat_graph; 720 PetscErrorCode ierr; 721 722 PetscFunctionBegin; 723 /* free old CSR */ 724 ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr); 725 /* TODO: PCBDDCGraphSetAdjacency */ 726 /* get CSR into graph structure */ 727 if (copymode == PETSC_COPY_VALUES) { 728 ierr = PetscMalloc1((nvtxs+1),&mat_graph->xadj);CHKERRQ(ierr); 729 ierr = PetscMalloc1(xadj[nvtxs],&mat_graph->adjncy);CHKERRQ(ierr); 730 ierr = PetscMemcpy(mat_graph->xadj,xadj,(nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr); 731 ierr = PetscMemcpy(mat_graph->adjncy,adjncy,xadj[nvtxs]*sizeof(PetscInt));CHKERRQ(ierr); 732 } else if (copymode == PETSC_OWN_POINTER) { 733 mat_graph->xadj = (PetscInt*)xadj; 734 mat_graph->adjncy = (PetscInt*)adjncy; 735 } 736 mat_graph->nvtxs_csr = nvtxs; 737 PetscFunctionReturn(0); 738 } 739 740 #undef __FUNCT__ 741 #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph" 742 /*@ 743 PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local Neumann matrix 744 745 Not collective 746 747 Input Parameters: 748 + pc - the preconditioning context 749 . nvtxs - number of local vertices of the graph (i.e., the local size of your problem) 750 . xadj, adjncy - the CSR graph 751 - copymode - either PETSC_COPY_VALUES or PETSC_OWN_POINTER. 752 753 Level: intermediate 754 755 Notes: 756 757 .seealso: PCBDDC,PetscCopyMode 758 @*/ 759 PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode) 760 { 761 void (*f)(void) = 0; 762 PetscErrorCode ierr; 763 764 PetscFunctionBegin; 765 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 766 PetscValidIntPointer(xadj,3); 767 PetscValidIntPointer(adjncy,4); 768 if (copymode != PETSC_COPY_VALUES && copymode != PETSC_OWN_POINTER) { 769 SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %d in %s\n",copymode,__FUNCT__); 770 } 771 ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr); 772 /* free arrays if PCBDDC is not the PC type */ 773 ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr); 774 if (!f && copymode == PETSC_OWN_POINTER) { 775 ierr = PetscFree(xadj);CHKERRQ(ierr); 776 ierr = PetscFree(adjncy);CHKERRQ(ierr); 777 } 778 PetscFunctionReturn(0); 779 } 780 /* -------------------------------------------------------------------------- */ 781 782 #undef __FUNCT__ 783 #define __FUNCT__ "PCBDDCSetDofsSplittingLocal_BDDC" 784 static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc,PetscInt n_is, IS ISForDofs[]) 785 { 786 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 787 PetscInt i; 788 PetscErrorCode ierr; 789 790 PetscFunctionBegin; 791 /* Destroy ISes if they were already set */ 792 for (i=0;i<pcbddc->n_ISForDofsLocal;i++) { 793 ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr); 794 } 795 ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr); 796 /* last user setting takes precendence -> destroy any other customization */ 797 for (i=0;i<pcbddc->n_ISForDofs;i++) { 798 ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr); 799 } 800 ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr); 801 pcbddc->n_ISForDofs = 0; 802 /* allocate space then set */ 803 ierr = PetscMalloc(n_is*sizeof(IS),&pcbddc->ISForDofsLocal);CHKERRQ(ierr); 804 for (i=0;i<n_is;i++) { 805 ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr); 806 pcbddc->ISForDofsLocal[i]=ISForDofs[i]; 807 } 808 pcbddc->n_ISForDofsLocal=n_is; 809 if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE; 810 pcbddc->recompute_topography = PETSC_TRUE; 811 PetscFunctionReturn(0); 812 } 813 814 #undef __FUNCT__ 815 #define __FUNCT__ "PCBDDCSetDofsSplittingLocal" 816 /*@ 817 PCBDDCSetDofsSplittingLocal - Set index sets defining fields of the local subdomain matrix 818 819 Collective 820 821 Input Parameters: 822 + pc - the preconditioning context 823 - n_is - number of index sets defining the fields 824 . ISForDofs - array of IS describing the fields in local ordering 825 826 Level: intermediate 827 828 Notes: n_is should be the same among processes. Not all nodes need to be listed: unlisted nodes will belong to a different field. 829 830 .seealso: PCBDDC 831 @*/ 832 PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc,PetscInt n_is, IS ISForDofs[]) 833 { 834 PetscInt i; 835 PetscErrorCode ierr; 836 837 PetscFunctionBegin; 838 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 839 PetscValidLogicalCollectiveInt(pc,n_is,2); 840 for (i=0;i<n_is;i++) { 841 PetscCheckSameComm(pc,1,ISForDofs[i],3); 842 PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3); 843 } 844 ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr); 845 PetscFunctionReturn(0); 846 } 847 /* -------------------------------------------------------------------------- */ 848 849 #undef __FUNCT__ 850 #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC" 851 static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[]) 852 { 853 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 854 PetscInt i; 855 PetscErrorCode ierr; 856 857 PetscFunctionBegin; 858 /* Destroy ISes if they were already set */ 859 for (i=0;i<pcbddc->n_ISForDofs;i++) { 860 ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr); 861 } 862 ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr); 863 /* last user setting takes precendence -> destroy any other customization */ 864 for (i=0;i<pcbddc->n_ISForDofsLocal;i++) { 865 ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr); 866 } 867 ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr); 868 pcbddc->n_ISForDofsLocal = 0; 869 /* allocate space then set */ 870 ierr = PetscMalloc1(n_is,&pcbddc->ISForDofs);CHKERRQ(ierr); 871 for (i=0;i<n_is;i++) { 872 ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr); 873 pcbddc->ISForDofs[i]=ISForDofs[i]; 874 } 875 pcbddc->n_ISForDofs=n_is; 876 if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE; 877 pcbddc->recompute_topography = PETSC_TRUE; 878 PetscFunctionReturn(0); 879 } 880 881 #undef __FUNCT__ 882 #define __FUNCT__ "PCBDDCSetDofsSplitting" 883 /*@ 884 PCBDDCSetDofsSplitting - Set index sets defining fields of the global matrix 885 886 Collective 887 888 Input Parameters: 889 + pc - the preconditioning context 890 - n_is - number of index sets defining the fields 891 . ISForDofs - array of IS describing the fields in global ordering 892 893 Level: intermediate 894 895 Notes: Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to a different field. 896 897 .seealso: PCBDDC 898 @*/ 899 PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[]) 900 { 901 PetscInt i; 902 PetscErrorCode ierr; 903 904 PetscFunctionBegin; 905 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 906 PetscValidLogicalCollectiveInt(pc,n_is,2); 907 for (i=0;i<n_is;i++) { 908 PetscCheckSameComm(pc,1,ISForDofs[i],3); 909 PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3); 910 } 911 ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr); 912 PetscFunctionReturn(0); 913 } 914 915 /* -------------------------------------------------------------------------- */ 916 #undef __FUNCT__ 917 #define __FUNCT__ "PCPreSolve_BDDC" 918 /* -------------------------------------------------------------------------- */ 919 /* 920 PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial 921 guess if a transformation of basis approach has been selected. 922 923 Input Parameter: 924 + pc - the preconditioner contex 925 926 Application Interface Routine: PCPreSolve() 927 928 Notes: 929 The interface routine PCPreSolve() is not usually called directly by 930 the user, but instead is called by KSPSolve(). 931 */ 932 static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x) 933 { 934 PetscErrorCode ierr; 935 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 936 PC_IS *pcis = (PC_IS*)(pc->data); 937 IS dirIS; 938 Vec used_vec; 939 940 PetscFunctionBegin; 941 /* if we are working with cg, one dirichlet solve can be avoided during Krylov iterations */ 942 if (ksp) { 943 PetscBool iscg; 944 ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPCG,&iscg);CHKERRQ(ierr); 945 if (!iscg) { 946 ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr); 947 } 948 } 949 /* Creates parallel work vectors used in presolve */ 950 if (!pcbddc->original_rhs) { 951 ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr); 952 } 953 if (!pcbddc->temp_solution) { 954 ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr); 955 } 956 if (x) { 957 ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr); 958 used_vec = x; 959 } else { 960 ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr); 961 used_vec = pcbddc->temp_solution; 962 ierr = VecSet(used_vec,0.0);CHKERRQ(ierr); 963 } 964 /* hack into ksp data structure PCPreSolve comes earlier in src/ksp/ksp/interface/itfunc.c */ 965 if (ksp) { 966 PetscBool guess_nonzero; 967 ierr = KSPGetInitialGuessNonzero(ksp,&guess_nonzero);CHKERRQ(ierr); 968 if (!guess_nonzero) { 969 ierr = VecSet(used_vec,0.0);CHKERRQ(ierr); 970 } 971 } 972 973 /* store the original rhs */ 974 ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr); 975 976 /* Take into account zeroed rows -> change rhs and store solution removed */ 977 /* note that Dirichlet boundaries in global ordering (if any) has already been translated into local ordering in PCBDDCAnalyzeInterface */ 978 ierr = PCBDDCGetDirichletBoundariesLocal(pc,&dirIS);CHKERRQ(ierr); 979 if (rhs && dirIS) { 980 Mat_IS *matis = (Mat_IS*)pc->pmat->data; 981 PetscInt dirsize,i,*is_indices; 982 PetscScalar *array_x,*array_diagonal; 983 984 ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr); 985 ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr); 986 ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 987 ierr = VecScatterEnd(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 988 ierr = VecScatterBegin(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 989 ierr = VecScatterEnd(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 990 ierr = ISGetLocalSize(dirIS,&dirsize);CHKERRQ(ierr); 991 ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr); 992 ierr = VecGetArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr); 993 ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr); 994 for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]]; 995 ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr); 996 ierr = VecRestoreArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr); 997 ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr); 998 ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 999 ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1000 1001 /* remove the computed solution from the rhs */ 1002 ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr); 1003 ierr = MatMultAdd(pc->pmat,used_vec,rhs,rhs);CHKERRQ(ierr); 1004 ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr); 1005 } 1006 1007 /* store partially computed solution and set initial guess */ 1008 if (x) { 1009 ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr); 1010 ierr = VecSet(used_vec,0.0);CHKERRQ(ierr); 1011 if (pcbddc->use_exact_dirichlet_trick) { 1012 ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1013 ierr = VecScatterEnd(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1014 ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr); 1015 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1016 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1017 if (ksp) { 1018 ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr); 1019 } 1020 } 1021 } 1022 1023 if (pcbddc->ChangeOfBasisMatrix) { 1024 PCBDDCChange_ctx change_ctx; 1025 1026 /* get change ctx */ 1027 ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr); 1028 1029 /* set current iteration matrix inside change context (change of basis has been already set into the ctx during PCSetUp) */ 1030 ierr = MatDestroy(&change_ctx->original_mat);CHKERRQ(ierr); 1031 ierr = PetscObjectReference((PetscObject)pc->mat);CHKERRQ(ierr); 1032 change_ctx->original_mat = pc->mat; 1033 1034 /* change iteration matrix */ 1035 ierr = MatDestroy(&pc->mat);CHKERRQ(ierr); 1036 ierr = PetscObjectReference((PetscObject)pcbddc->new_global_mat);CHKERRQ(ierr); 1037 pc->mat = pcbddc->new_global_mat; 1038 1039 /* change rhs */ 1040 ierr = MatMultTranspose(change_ctx->global_change,rhs,pcis->vec1_global);CHKERRQ(ierr); 1041 ierr = VecCopy(pcis->vec1_global,rhs);CHKERRQ(ierr); 1042 } 1043 1044 /* remove nullspace if present */ 1045 if (ksp && pcbddc->NullSpace) { 1046 ierr = MatNullSpaceRemove(pcbddc->NullSpace,used_vec);CHKERRQ(ierr); 1047 ierr = MatNullSpaceRemove(pcbddc->NullSpace,rhs);CHKERRQ(ierr); 1048 } 1049 ierr = VecDestroy(&used_vec);CHKERRQ(ierr); 1050 PetscFunctionReturn(0); 1051 } 1052 1053 /* -------------------------------------------------------------------------- */ 1054 #undef __FUNCT__ 1055 #define __FUNCT__ "PCPostSolve_BDDC" 1056 /* -------------------------------------------------------------------------- */ 1057 /* 1058 PCPostSolve_BDDC - Changes the computed solution if a transformation of basis 1059 approach has been selected. Also, restores rhs to its original state. 1060 1061 Input Parameter: 1062 + pc - the preconditioner contex 1063 1064 Application Interface Routine: PCPostSolve() 1065 1066 Notes: 1067 The interface routine PCPostSolve() is not usually called directly by 1068 the user, but instead is called by KSPSolve(). 1069 */ 1070 static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x) 1071 { 1072 PetscErrorCode ierr; 1073 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 1074 1075 PetscFunctionBegin; 1076 if (pcbddc->ChangeOfBasisMatrix) { 1077 PCBDDCChange_ctx change_ctx; 1078 1079 /* get change ctx */ 1080 ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr); 1081 1082 /* restore iteration matrix */ 1083 ierr = MatDestroy(&pc->mat);CHKERRQ(ierr); 1084 ierr = PetscObjectReference((PetscObject)change_ctx->original_mat);CHKERRQ(ierr); 1085 pc->mat = change_ctx->original_mat; 1086 1087 /* get solution in original basis */ 1088 if (x) { 1089 PC_IS *pcis = (PC_IS*)(pc->data); 1090 ierr = MatMult(change_ctx->global_change,x,pcis->vec1_global);CHKERRQ(ierr); 1091 ierr = VecCopy(pcis->vec1_global,x);CHKERRQ(ierr); 1092 } 1093 } 1094 1095 /* add solution removed in presolve */ 1096 if (x) { 1097 ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr); 1098 } 1099 1100 /* restore rhs to its original state */ 1101 if (rhs) { 1102 ierr = VecCopy(pcbddc->original_rhs,rhs);CHKERRQ(ierr); 1103 } 1104 PetscFunctionReturn(0); 1105 } 1106 /* -------------------------------------------------------------------------- */ 1107 #undef __FUNCT__ 1108 #define __FUNCT__ "PCSetUp_BDDC" 1109 /* -------------------------------------------------------------------------- */ 1110 /* 1111 PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner 1112 by setting data structures and options. 1113 1114 Input Parameter: 1115 + pc - the preconditioner context 1116 1117 Application Interface Routine: PCSetUp() 1118 1119 Notes: 1120 The interface routine PCSetUp() is not usually called directly by 1121 the user, but instead is called by PCApply() if necessary. 1122 */ 1123 PetscErrorCode PCSetUp_BDDC(PC pc) 1124 { 1125 PetscErrorCode ierr; 1126 PC_BDDC* pcbddc = (PC_BDDC*)pc->data; 1127 MatNullSpace nearnullspace; 1128 PetscBool computeis,computetopography,computesolvers; 1129 PetscBool new_nearnullspace_provided; 1130 1131 PetscFunctionBegin; 1132 /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */ 1133 /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup 1134 Also, BDDC directly build the Dirichlet problem */ 1135 /* split work */ 1136 if (pc->setupcalled) { 1137 computeis = PETSC_FALSE; 1138 if (pc->flag == SAME_NONZERO_PATTERN) { 1139 computetopography = PETSC_FALSE; 1140 computesolvers = PETSC_TRUE; 1141 } else { /* DIFFERENT_NONZERO_PATTERN */ 1142 computetopography = PETSC_TRUE; 1143 computesolvers = PETSC_TRUE; 1144 } 1145 } else { 1146 computeis = PETSC_TRUE; 1147 computetopography = PETSC_TRUE; 1148 computesolvers = PETSC_TRUE; 1149 } 1150 if (pcbddc->recompute_topography) { 1151 computetopography = PETSC_TRUE; 1152 } 1153 1154 /* Get stdout for dbg */ 1155 if (pcbddc->dbg_flag) { 1156 if (!pcbddc->dbg_viewer) { 1157 pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc)); 1158 ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr); 1159 } 1160 ierr = PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr); 1161 } 1162 1163 /* Set up all the "iterative substructuring" common block without computing solvers */ 1164 if (computeis) { 1165 /* HACK INTO PCIS */ 1166 PC_IS* pcis = (PC_IS*)pc->data; 1167 pcis->computesolvers = PETSC_FALSE; 1168 ierr = PCISSetUp(pc);CHKERRQ(ierr); 1169 ierr = ISLocalToGlobalMappingCreateIS(pcis->is_B_local,&pcbddc->BtoNmap);CHKERRQ(ierr); 1170 } 1171 1172 /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */ 1173 if (pcbddc->user_ChangeOfBasisMatrix) { 1174 pcbddc->use_change_of_basis = PETSC_FALSE; 1175 } 1176 1177 /* Analyze interface */ 1178 if (computetopography) { 1179 ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr); 1180 /* Schurs on subsets should be reset */ 1181 if (pcbddc->deluxe_ctx) { 1182 ierr = PCBDDCSubSchursReset(pcbddc->deluxe_ctx->sub_schurs);CHKERRQ(ierr); 1183 } 1184 } 1185 1186 /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */ 1187 new_nearnullspace_provided = PETSC_FALSE; 1188 ierr = MatGetNearNullSpace(pc->pmat,&nearnullspace);CHKERRQ(ierr); 1189 if (pcbddc->onearnullspace) { /* already used nearnullspace */ 1190 if (!nearnullspace) { /* near null space attached to mat has been destroyed */ 1191 new_nearnullspace_provided = PETSC_TRUE; 1192 } else { 1193 /* determine if the two nullspaces are different (should be lightweight) */ 1194 if (nearnullspace != pcbddc->onearnullspace) { 1195 new_nearnullspace_provided = PETSC_TRUE; 1196 } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */ 1197 PetscInt i; 1198 const Vec *nearnullvecs; 1199 PetscObjectState state; 1200 PetscInt nnsp_size; 1201 ierr = MatNullSpaceGetVecs(nearnullspace,NULL,&nnsp_size,&nearnullvecs);CHKERRQ(ierr); 1202 for (i=0;i<nnsp_size;i++) { 1203 ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&state);CHKERRQ(ierr); 1204 if (pcbddc->onearnullvecs_state[i] != state) { 1205 new_nearnullspace_provided = PETSC_TRUE; 1206 break; 1207 } 1208 } 1209 } 1210 } 1211 } else { 1212 if (!nearnullspace) { /* both nearnullspaces are null */ 1213 new_nearnullspace_provided = PETSC_FALSE; 1214 } else { /* nearnullspace attached later */ 1215 new_nearnullspace_provided = PETSC_TRUE; 1216 } 1217 } 1218 1219 /* Setup constraints and related work vectors */ 1220 /* reset primal space flags */ 1221 pcbddc->new_primal_space = PETSC_FALSE; 1222 pcbddc->new_primal_space_local = PETSC_FALSE; 1223 if (computetopography || new_nearnullspace_provided) { 1224 /* It also sets the primal space flags */ 1225 ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr); 1226 /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */ 1227 ierr = PCBDDCSetUpLocalWorkVectors(pc);CHKERRQ(ierr); 1228 /* Schurs on subsets should be reset */ 1229 if (pcbddc->deluxe_ctx) { 1230 ierr = PCBDDCSubSchursReset(pcbddc->deluxe_ctx->sub_schurs);CHKERRQ(ierr); 1231 } 1232 } 1233 1234 if (computesolvers || pcbddc->new_primal_space) { 1235 /* Create coarse and local stuffs */ 1236 ierr = PCBDDCSetUpSolvers(pc);CHKERRQ(ierr); 1237 /* Create scaling operators */ 1238 ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr); 1239 } 1240 1241 if (pcbddc->dbg_flag) { 1242 ierr = PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr); 1243 } 1244 PetscFunctionReturn(0); 1245 } 1246 1247 /* -------------------------------------------------------------------------- */ 1248 /* 1249 PCApply_BDDC - Applies the BDDC operator to a vector. 1250 1251 Input Parameters: 1252 . pc - the preconditioner context 1253 . r - input vector (global) 1254 1255 Output Parameter: 1256 . z - output vector (global) 1257 1258 Application Interface Routine: PCApply() 1259 */ 1260 #undef __FUNCT__ 1261 #define __FUNCT__ "PCApply_BDDC" 1262 PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z) 1263 { 1264 PC_IS *pcis = (PC_IS*)(pc->data); 1265 PC_BDDC *pcbddc = (PC_BDDC*)(pc->data); 1266 PetscErrorCode ierr; 1267 const PetscScalar one = 1.0; 1268 const PetscScalar m_one = -1.0; 1269 const PetscScalar zero = 0.0; 1270 1271 /* This code is similar to that provided in nn.c for PCNN 1272 NN interface preconditioner changed to BDDC 1273 Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static = PETSC_TRUE) */ 1274 1275 PetscFunctionBegin; 1276 if (!pcbddc->use_exact_dirichlet_trick) { 1277 /* First Dirichlet solve */ 1278 ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1279 ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1280 ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr); 1281 /* 1282 Assembling right hand side for BDDC operator 1283 - pcis->vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE) 1284 - pcis->vec1_B the interface part of the global vector z 1285 */ 1286 ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr); 1287 ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr); 1288 if (pcbddc->switch_static) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); } 1289 ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr); 1290 ierr = VecCopy(r,z);CHKERRQ(ierr); 1291 ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1292 ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1293 ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr); 1294 } else { 1295 ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr); 1296 ierr = VecSet(pcis->vec2_D,zero);CHKERRQ(ierr); 1297 ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr); 1298 } 1299 1300 /* Apply interface preconditioner 1301 input/output vecs: pcis->vec1_B and pcis->vec1_D */ 1302 ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr); 1303 1304 /* Apply transpose of partition of unity operator */ 1305 ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr); 1306 1307 /* Second Dirichlet solve and assembling of output */ 1308 ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1309 ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1310 ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr); 1311 if (pcbddc->switch_static) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); } 1312 ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr); 1313 ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr); 1314 if (pcbddc->switch_static) { ierr = VecAXPY(pcis->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); } 1315 ierr = VecAXPY(pcis->vec2_D,one,pcis->vec4_D);CHKERRQ(ierr); 1316 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1317 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1318 PetscFunctionReturn(0); 1319 } 1320 1321 /* -------------------------------------------------------------------------- */ 1322 /* 1323 PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector. 1324 1325 Input Parameters: 1326 . pc - the preconditioner context 1327 . r - input vector (global) 1328 1329 Output Parameter: 1330 . z - output vector (global) 1331 1332 Application Interface Routine: PCApplyTranspose() 1333 */ 1334 #undef __FUNCT__ 1335 #define __FUNCT__ "PCApplyTranspose_BDDC" 1336 PetscErrorCode PCApplyTranspose_BDDC(PC pc,Vec r,Vec z) 1337 { 1338 PC_IS *pcis = (PC_IS*)(pc->data); 1339 PC_BDDC *pcbddc = (PC_BDDC*)(pc->data); 1340 PetscErrorCode ierr; 1341 const PetscScalar one = 1.0; 1342 const PetscScalar m_one = -1.0; 1343 const PetscScalar zero = 0.0; 1344 1345 PetscFunctionBegin; 1346 if (!pcbddc->use_exact_dirichlet_trick) { 1347 /* First Dirichlet solve */ 1348 ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1349 ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1350 ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr); 1351 /* 1352 Assembling right hand side for BDDC operator 1353 - pcis->vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE) 1354 - pcis->vec1_B the interface part of the global vector z 1355 */ 1356 ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr); 1357 ierr = MatMultTranspose(pcis->A_IB,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr); 1358 if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); } 1359 ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr); 1360 ierr = VecCopy(r,z);CHKERRQ(ierr); 1361 ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1362 ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1363 ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr); 1364 } else { 1365 ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr); 1366 ierr = VecSet(pcis->vec2_D,zero);CHKERRQ(ierr); 1367 ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr); 1368 } 1369 1370 /* Apply interface preconditioner 1371 input/output vecs: pcis->vec1_B and pcis->vec1_D */ 1372 ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_TRUE);CHKERRQ(ierr); 1373 1374 /* Apply transpose of partition of unity operator */ 1375 ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr); 1376 1377 /* Second Dirichlet solve and assembling of output */ 1378 ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1379 ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1380 ierr = MatMultTranspose(pcis->A_BI,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr); 1381 if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); } 1382 ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr); 1383 ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr); 1384 if (pcbddc->switch_static) { ierr = VecAXPY(pcis->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); } 1385 ierr = VecAXPY(pcis->vec2_D,one,pcis->vec4_D);CHKERRQ(ierr); 1386 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1387 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1388 PetscFunctionReturn(0); 1389 } 1390 /* -------------------------------------------------------------------------- */ 1391 1392 #undef __FUNCT__ 1393 #define __FUNCT__ "PCDestroy_BDDC" 1394 PetscErrorCode PCDestroy_BDDC(PC pc) 1395 { 1396 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 1397 PetscErrorCode ierr; 1398 1399 PetscFunctionBegin; 1400 /* free data created by PCIS */ 1401 ierr = PCISDestroy(pc);CHKERRQ(ierr); 1402 /* free BDDC custom data */ 1403 ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr); 1404 /* destroy objects related to topography */ 1405 ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr); 1406 /* free allocated graph structure */ 1407 ierr = PetscFree(pcbddc->mat_graph);CHKERRQ(ierr); 1408 /* destroy objects for scaling operator */ 1409 ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr); 1410 ierr = PetscFree(pcbddc->deluxe_ctx);CHKERRQ(ierr); 1411 /* free solvers stuff */ 1412 ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr); 1413 /* free global vectors needed in presolve */ 1414 ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr); 1415 ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr); 1416 /* free stuff for change of basis hooks */ 1417 if (pcbddc->new_global_mat) { 1418 PCBDDCChange_ctx change_ctx; 1419 ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr); 1420 ierr = MatDestroy(&change_ctx->original_mat);CHKERRQ(ierr); 1421 ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr); 1422 ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr); 1423 ierr = PetscFree(change_ctx);CHKERRQ(ierr); 1424 } 1425 ierr = MatDestroy(&pcbddc->new_global_mat);CHKERRQ(ierr); 1426 /* remove map from local boundary to local numbering */ 1427 ierr = ISLocalToGlobalMappingDestroy(&pcbddc->BtoNmap);CHKERRQ(ierr); 1428 /* remove functions */ 1429 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",NULL);CHKERRQ(ierr); 1430 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr); 1431 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr); 1432 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL);CHKERRQ(ierr); 1433 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL);CHKERRQ(ierr); 1434 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL);CHKERRQ(ierr); 1435 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",NULL);CHKERRQ(ierr); 1436 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr); 1437 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr); 1438 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr); 1439 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr); 1440 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr); 1441 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr); 1442 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr); 1443 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr); 1444 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr); 1445 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",NULL);CHKERRQ(ierr); 1446 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr); 1447 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr); 1448 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr); 1449 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr); 1450 /* Free the private data structure */ 1451 ierr = PetscFree(pc->data);CHKERRQ(ierr); 1452 PetscFunctionReturn(0); 1453 } 1454 /* -------------------------------------------------------------------------- */ 1455 1456 #undef __FUNCT__ 1457 #define __FUNCT__ "PCBDDCMatFETIDPGetRHS_BDDC" 1458 static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) 1459 { 1460 FETIDPMat_ctx mat_ctx; 1461 PC_IS* pcis; 1462 PC_BDDC* pcbddc; 1463 PetscErrorCode ierr; 1464 1465 PetscFunctionBegin; 1466 ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr); 1467 pcis = (PC_IS*)mat_ctx->pc->data; 1468 pcbddc = (PC_BDDC*)mat_ctx->pc->data; 1469 1470 /* change of basis for physical rhs if needed 1471 It also changes the rhs in case of dirichlet boundaries */ 1472 ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,standard_rhs,NULL);CHKERRQ(ierr); 1473 /* store vectors for computation of fetidp final solution */ 1474 ierr = VecScatterBegin(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1475 ierr = VecScatterEnd(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1476 /* scale rhs since it should be unassembled */ 1477 /* TODO use counter scaling? (also below) */ 1478 ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1479 ierr = VecScatterEnd(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1480 /* Apply partition of unity */ 1481 ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr); 1482 /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */ 1483 if (!pcbddc->switch_static) { 1484 /* compute partially subassembled Schur complement right-hand side */ 1485 ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr); 1486 ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr); 1487 ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr); 1488 ierr = VecSet(standard_rhs,0.0);CHKERRQ(ierr); 1489 ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1490 ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1491 /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */ 1492 ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1493 ierr = VecScatterEnd(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1494 ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr); 1495 } 1496 /* BDDC rhs */ 1497 ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr); 1498 if (pcbddc->switch_static) { 1499 ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr); 1500 } 1501 /* apply BDDC */ 1502 ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr); 1503 /* Application of B_delta and assembling of rhs for fetidp fluxes */ 1504 ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr); 1505 ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr); 1506 ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1507 ierr = VecScatterEnd (mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1508 /* restore original rhs */ 1509 ierr = VecCopy(pcbddc->original_rhs,standard_rhs);CHKERRQ(ierr); 1510 PetscFunctionReturn(0); 1511 } 1512 1513 #undef __FUNCT__ 1514 #define __FUNCT__ "PCBDDCMatFETIDPGetRHS" 1515 /*@ 1516 PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETIDP linear system 1517 1518 Collective 1519 1520 Input Parameters: 1521 + fetidp_mat - the FETIDP matrix object obtained by calling PCBDDCCreateFETIDPOperators 1522 . standard_rhs - the right-hand side for your linear system 1523 1524 Output Parameters: 1525 - fetidp_flux_rhs - the right-hand side for the FETIDP linear system 1526 1527 Level: developer 1528 1529 Notes: 1530 1531 .seealso: PCBDDC,PCBDDCCreateFETIDPOperators 1532 @*/ 1533 PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) 1534 { 1535 FETIDPMat_ctx mat_ctx; 1536 PetscErrorCode ierr; 1537 1538 PetscFunctionBegin; 1539 ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr); 1540 ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr); 1541 PetscFunctionReturn(0); 1542 } 1543 /* -------------------------------------------------------------------------- */ 1544 1545 #undef __FUNCT__ 1546 #define __FUNCT__ "PCBDDCMatFETIDPGetSolution_BDDC" 1547 static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) 1548 { 1549 FETIDPMat_ctx mat_ctx; 1550 PC_IS* pcis; 1551 PC_BDDC* pcbddc; 1552 PetscErrorCode ierr; 1553 1554 PetscFunctionBegin; 1555 ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr); 1556 pcis = (PC_IS*)mat_ctx->pc->data; 1557 pcbddc = (PC_BDDC*)mat_ctx->pc->data; 1558 1559 /* apply B_delta^T */ 1560 ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1561 ierr = VecScatterEnd (mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1562 ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr); 1563 /* compute rhs for BDDC application */ 1564 ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr); 1565 if (pcbddc->switch_static) { 1566 ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr); 1567 } 1568 /* apply BDDC */ 1569 ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr); 1570 /* put values into standard global vector */ 1571 ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1572 ierr = VecScatterEnd (pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1573 if (!pcbddc->switch_static) { 1574 /* compute values into the interior if solved for the partially subassembled Schur complement */ 1575 ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr); 1576 ierr = VecAXPY(mat_ctx->temp_solution_D,-1.0,pcis->vec1_D);CHKERRQ(ierr); 1577 ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr); 1578 } 1579 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1580 ierr = VecScatterEnd (pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1581 /* final change of basis if needed 1582 Is also sums the dirichlet part removed during RHS assembling */ 1583 ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr); 1584 PetscFunctionReturn(0); 1585 } 1586 1587 #undef __FUNCT__ 1588 #define __FUNCT__ "PCBDDCMatFETIDPGetSolution" 1589 /*@ 1590 PCBDDCMatFETIDPGetSolution - Compute the physical solution from the solution of the FETIDP linear system 1591 1592 Collective 1593 1594 Input Parameters: 1595 + fetidp_mat - the FETIDP matrix obtained by calling PCBDDCCreateFETIDPOperators 1596 . fetidp_flux_sol - the solution of the FETIDP linear system 1597 1598 Output Parameters: 1599 - standard_sol - the solution defined on the physical domain 1600 1601 Level: developer 1602 1603 Notes: 1604 1605 .seealso: PCBDDC,PCBDDCCreateFETIDPOperators 1606 @*/ 1607 PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) 1608 { 1609 FETIDPMat_ctx mat_ctx; 1610 PetscErrorCode ierr; 1611 1612 PetscFunctionBegin; 1613 ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr); 1614 ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr); 1615 PetscFunctionReturn(0); 1616 } 1617 /* -------------------------------------------------------------------------- */ 1618 1619 extern PetscErrorCode FETIDPMatMult(Mat,Vec,Vec); 1620 extern PetscErrorCode FETIDPMatMultTranspose(Mat,Vec,Vec); 1621 extern PetscErrorCode PCBDDCDestroyFETIDPMat(Mat); 1622 extern PetscErrorCode FETIDPPCApply(PC,Vec,Vec); 1623 extern PetscErrorCode FETIDPPCApplyTranspose(PC,Vec,Vec); 1624 extern PetscErrorCode PCBDDCDestroyFETIDPPC(PC); 1625 1626 #undef __FUNCT__ 1627 #define __FUNCT__ "PCBDDCCreateFETIDPOperators_BDDC" 1628 static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, Mat *fetidp_mat, PC *fetidp_pc) 1629 { 1630 1631 FETIDPMat_ctx fetidpmat_ctx; 1632 Mat newmat; 1633 FETIDPPC_ctx fetidppc_ctx; 1634 PC newpc; 1635 MPI_Comm comm; 1636 PetscErrorCode ierr; 1637 1638 PetscFunctionBegin; 1639 ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr); 1640 /* FETIDP linear matrix */ 1641 ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr); 1642 ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr); 1643 ierr = MatCreateShell(comm,PETSC_DECIDE,PETSC_DECIDE,fetidpmat_ctx->n_lambda,fetidpmat_ctx->n_lambda,fetidpmat_ctx,&newmat);CHKERRQ(ierr); 1644 ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr); 1645 ierr = MatShellSetOperation(newmat,MATOP_MULT_TRANSPOSE,(void (*)(void))FETIDPMatMultTranspose);CHKERRQ(ierr); 1646 ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr); 1647 ierr = MatSetUp(newmat);CHKERRQ(ierr); 1648 /* FETIDP preconditioner */ 1649 ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr); 1650 ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr); 1651 ierr = PCCreate(comm,&newpc);CHKERRQ(ierr); 1652 ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr); 1653 ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr); 1654 ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr); 1655 ierr = PCShellSetApplyTranspose(newpc,FETIDPPCApplyTranspose);CHKERRQ(ierr); 1656 ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr); 1657 ierr = PCSetOperators(newpc,newmat,newmat);CHKERRQ(ierr); 1658 ierr = PCSetUp(newpc);CHKERRQ(ierr); 1659 /* return pointers for objects created */ 1660 *fetidp_mat=newmat; 1661 *fetidp_pc=newpc; 1662 PetscFunctionReturn(0); 1663 } 1664 1665 #undef __FUNCT__ 1666 #define __FUNCT__ "PCBDDCCreateFETIDPOperators" 1667 /*@ 1668 PCBDDCCreateFETIDPOperators - Create operators for FETIDP 1669 1670 Collective 1671 1672 Input Parameters: 1673 + pc - the BDDC preconditioning context already setup 1674 1675 Output Parameters: 1676 . fetidp_mat - shell FETIDP matrix object 1677 . fetidp_pc - shell Dirichlet preconditioner for FETIDP matrix 1678 1679 Options Database Keys: 1680 - -fetidp_fullyredundant: use or not a fully redundant set of Lagrange multipliers 1681 1682 Level: developer 1683 1684 Notes: 1685 Currently the only operation provided for FETIDP matrix is MatMult 1686 1687 .seealso: PCBDDC 1688 @*/ 1689 PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, Mat *fetidp_mat, PC *fetidp_pc) 1690 { 1691 PetscErrorCode ierr; 1692 1693 PetscFunctionBegin; 1694 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1695 if (pc->setupcalled) { 1696 ierr = PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,Mat*,PC*),(pc,fetidp_mat,fetidp_pc));CHKERRQ(ierr); 1697 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"You must call PCSetup_BDDC() first \n"); 1698 PetscFunctionReturn(0); 1699 } 1700 /* -------------------------------------------------------------------------- */ 1701 /*MC 1702 PCBDDC - Balancing Domain Decomposition by Constraints. 1703 1704 An implementation of the BDDC preconditioner based on 1705 1706 .vb 1707 [1] C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007 1708 [2] A. Klawonn and O. B. Widlund. "Dual-Primal FETI Methods for Linear Elasticity", http://cs.nyu.edu/csweb/Research/TechReports/TR2004-855/TR2004-855.pdf 1709 [3] J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", http://arxiv.org/abs/0712.3977 1710 .ve 1711 1712 The matrix to be preconditioned (Pmat) must be of type MATIS. 1713 1714 Currently works with MATIS matrices with local Neumann matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers. 1715 1716 It also works with unsymmetric and indefinite problems. 1717 1718 Unlike 'conventional' interface preconditioners, PCBDDC iterates over all degrees of freedom, not just those on the interface. This allows the use of approximate solvers on the subdomains. 1719 1720 Approximate local solvers are automatically adapted for singular linear problems (see [1]) if the user has provided the nullspace using PCBDDCSetNullSpace 1721 1722 Boundary nodes are split in vertices, edges and faces using information from the local to global mapping of dofs and the local connectivity graph of nodes. The latter can be customized by using PCBDDCSetLocalAdjacencyGraph() 1723 1724 Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). 1725 1726 Change of basis is performed similarly to [2] when requested. When more the one constraint is present on a single connected component (i.e. an edge or a face), a robust method based on local QR factorizations is used. 1727 1728 The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using MatPartitioning object. 1729 1730 Options Database Keys: 1731 1732 . -pc_bddc_use_vertices <1> - use or not vertices in primal space 1733 . -pc_bddc_use_edges <1> - use or not edges in primal space 1734 . -pc_bddc_use_faces <0> - use or not faces in primal space 1735 . -pc_bddc_use_change_of_basis <0> - use change of basis approach (on edges only) 1736 . -pc_bddc_use_change_on_faces <0> - use change of basis approach on faces if change of basis has been requested 1737 . -pc_bddc_switch_static <0> - switches from M_2 to M_3 operator (see reference article [1]) 1738 . -pc_bddc_levels <0> - maximum number of levels for multilevel 1739 . -pc_bddc_coarsening_ratio - H/h ratio at the coarser level 1740 - -pc_bddc_check_level <0> - set verbosity level of debugging output 1741 1742 Options for Dirichlet, Neumann or coarse solver can be set with 1743 .vb 1744 -pc_bddc_dirichlet_ 1745 -pc_bddc_neumann_ 1746 -pc_bddc_coarse_ 1747 .ve 1748 e.g -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg 1749 1750 When using a multilevel approach, solvers' options at the N-th level can be specified as 1751 .vb 1752 -pc_bddc_dirichlet_lN_ 1753 -pc_bddc_neumann_lN_ 1754 -pc_bddc_coarse_lN_ 1755 .ve 1756 Note that level number ranges from the finest 0 to the coarsest N. 1757 1758 Level: intermediate 1759 1760 Developer notes: 1761 1762 New deluxe scaling operator will be available soon. 1763 1764 Contributed by Stefano Zampini 1765 1766 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, MATIS 1767 M*/ 1768 1769 #undef __FUNCT__ 1770 #define __FUNCT__ "PCCreate_BDDC" 1771 PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc) 1772 { 1773 PetscErrorCode ierr; 1774 PC_BDDC *pcbddc; 1775 1776 PetscFunctionBegin; 1777 /* Creates the private data structure for this preconditioner and attach it to the PC object. */ 1778 ierr = PetscNewLog(pc,&pcbddc);CHKERRQ(ierr); 1779 pc->data = (void*)pcbddc; 1780 1781 /* create PCIS data structure */ 1782 ierr = PCISCreate(pc);CHKERRQ(ierr); 1783 1784 /* BDDC customization */ 1785 pcbddc->use_local_adj = PETSC_TRUE; 1786 pcbddc->use_vertices = PETSC_TRUE; 1787 pcbddc->use_edges = PETSC_TRUE; 1788 pcbddc->use_faces = PETSC_FALSE; 1789 pcbddc->use_change_of_basis = PETSC_FALSE; 1790 pcbddc->use_change_on_faces = PETSC_FALSE; 1791 pcbddc->switch_static = PETSC_FALSE; 1792 pcbddc->use_nnsp_true = PETSC_FALSE; /* not yet exposed */ 1793 pcbddc->dbg_flag = 0; 1794 /* private */ 1795 pcbddc->issym = PETSC_FALSE; 1796 pcbddc->BtoNmap = 0; 1797 pcbddc->local_primal_size = 0; 1798 pcbddc->n_vertices = 0; 1799 pcbddc->n_actual_vertices = 0; 1800 pcbddc->n_constraints = 0; 1801 pcbddc->primal_indices_local_idxs = 0; 1802 pcbddc->recompute_topography = PETSC_FALSE; 1803 pcbddc->coarse_size = -1; 1804 pcbddc->new_primal_space = PETSC_FALSE; 1805 pcbddc->new_primal_space_local = PETSC_FALSE; 1806 pcbddc->global_primal_indices = 0; 1807 pcbddc->onearnullspace = 0; 1808 pcbddc->onearnullvecs_state = 0; 1809 pcbddc->user_primal_vertices = 0; 1810 pcbddc->NullSpace = 0; 1811 pcbddc->temp_solution = 0; 1812 pcbddc->original_rhs = 0; 1813 pcbddc->local_mat = 0; 1814 pcbddc->ChangeOfBasisMatrix = 0; 1815 pcbddc->user_ChangeOfBasisMatrix = 0; 1816 pcbddc->new_global_mat = 0; 1817 pcbddc->coarse_vec = 0; 1818 pcbddc->coarse_rhs = 0; 1819 pcbddc->coarse_ksp = 0; 1820 pcbddc->coarse_phi_B = 0; 1821 pcbddc->coarse_phi_D = 0; 1822 pcbddc->coarse_psi_B = 0; 1823 pcbddc->coarse_psi_D = 0; 1824 pcbddc->vec1_P = 0; 1825 pcbddc->vec1_R = 0; 1826 pcbddc->vec2_R = 0; 1827 pcbddc->local_auxmat1 = 0; 1828 pcbddc->local_auxmat2 = 0; 1829 pcbddc->R_to_B = 0; 1830 pcbddc->R_to_D = 0; 1831 pcbddc->ksp_D = 0; 1832 pcbddc->ksp_R = 0; 1833 pcbddc->NeumannBoundaries = 0; 1834 pcbddc->NeumannBoundariesLocal = 0; 1835 pcbddc->DirichletBoundaries = 0; 1836 pcbddc->DirichletBoundariesLocal = 0; 1837 pcbddc->user_provided_isfordofs = PETSC_FALSE; 1838 pcbddc->n_ISForDofs = 0; 1839 pcbddc->n_ISForDofsLocal = 0; 1840 pcbddc->ISForDofs = 0; 1841 pcbddc->ISForDofsLocal = 0; 1842 pcbddc->ConstraintMatrix = 0; 1843 pcbddc->use_exact_dirichlet_trick = PETSC_TRUE; 1844 pcbddc->coarse_loc_to_glob = 0; 1845 pcbddc->coarsening_ratio = 8; 1846 pcbddc->current_level = 0; 1847 pcbddc->max_levels = 0; 1848 pcbddc->use_coarse_estimates = PETSC_FALSE; 1849 pcbddc->coarse_subassembling = 0; 1850 pcbddc->coarse_subassembling_init = 0; 1851 1852 /* create local graph structure */ 1853 ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr); 1854 1855 /* scaling */ 1856 pcbddc->work_scaling = 0; 1857 pcbddc->use_deluxe_scaling = PETSC_FALSE; 1858 pcbddc->deluxe_threshold = 1; 1859 pcbddc->deluxe_rebuild = PETSC_FALSE; 1860 pcbddc->deluxe_layers = -1; 1861 pcbddc->deluxe_use_useradj = PETSC_FALSE; 1862 pcbddc->deluxe_compute_rowadj = PETSC_TRUE; 1863 1864 /* function pointers */ 1865 pc->ops->apply = PCApply_BDDC; 1866 pc->ops->applytranspose = PCApplyTranspose_BDDC; 1867 pc->ops->setup = PCSetUp_BDDC; 1868 pc->ops->destroy = PCDestroy_BDDC; 1869 pc->ops->setfromoptions = PCSetFromOptions_BDDC; 1870 pc->ops->view = 0; 1871 pc->ops->applyrichardson = 0; 1872 pc->ops->applysymmetricleft = 0; 1873 pc->ops->applysymmetricright = 0; 1874 pc->ops->presolve = PCPreSolve_BDDC; 1875 pc->ops->postsolve = PCPostSolve_BDDC; 1876 1877 /* composing function */ 1878 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",PCBDDCSetChangeOfBasisMat_BDDC);CHKERRQ(ierr); 1879 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr); 1880 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr); 1881 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC);CHKERRQ(ierr); 1882 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC);CHKERRQ(ierr); 1883 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC);CHKERRQ(ierr); 1884 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",PCBDDCSetNullSpace_BDDC);CHKERRQ(ierr); 1885 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr); 1886 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",PCBDDCSetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr); 1887 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr); 1888 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",PCBDDCSetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr); 1889 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr); 1890 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",PCBDDCGetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr); 1891 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr); 1892 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",PCBDDCGetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr); 1893 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr); 1894 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",PCBDDCSetDofsSplittingLocal_BDDC);CHKERRQ(ierr); 1895 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr); 1896 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr); 1897 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr); 1898 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr); 1899 PetscFunctionReturn(0); 1900 } 1901 1902