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,"PCBDDCSetDofsSplittingLocal_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 PetscBool remove_rhs = PETSC_FALSE; 940 941 PetscFunctionBegin; 942 /* if we are working with cg, one dirichlet solve can be avoided during Krylov iterations */ 943 if (ksp) { 944 PetscBool iscg; 945 ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPCG,&iscg);CHKERRQ(ierr); 946 if (!iscg) { 947 ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr); 948 } 949 } 950 /* Creates parallel work vectors used in presolve */ 951 if (!pcbddc->original_rhs) { 952 ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr); 953 } 954 if (!pcbddc->temp_solution) { 955 ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr); 956 } 957 if (x) { 958 ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr); 959 used_vec = x; 960 } else { 961 ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr); 962 used_vec = pcbddc->temp_solution; 963 ierr = VecSet(used_vec,0.0);CHKERRQ(ierr); 964 } 965 966 /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */ 967 if (ksp) { 968 ierr = KSPGetInitialGuessNonzero(ksp,&pcbddc->ksp_guess_nonzero);CHKERRQ(ierr); 969 if (!pcbddc->ksp_guess_nonzero) { 970 ierr = VecSet(used_vec,0.0);CHKERRQ(ierr); 971 } 972 } 973 974 /* store the original rhs */ 975 ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr); 976 977 /* Take into account zeroed rows -> change rhs and store solution removed */ 978 /* note that Dirichlet boundaries in global ordering (if any) has already been translated into local ordering in PCBDDCAnalyzeInterface */ 979 ierr = PCBDDCGetDirichletBoundariesLocal(pc,&dirIS);CHKERRQ(ierr); 980 if (rhs && dirIS) { 981 Mat_IS *matis = (Mat_IS*)pc->pmat->data; 982 PetscInt dirsize,i,*is_indices; 983 PetscScalar *array_x,*array_diagonal; 984 985 ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr); 986 ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr); 987 ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 988 ierr = VecScatterEnd(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 989 ierr = VecScatterBegin(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 990 ierr = VecScatterEnd(matis->ctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 991 ierr = ISGetLocalSize(dirIS,&dirsize);CHKERRQ(ierr); 992 ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr); 993 ierr = VecGetArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr); 994 ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr); 995 for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]]; 996 ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr); 997 ierr = VecRestoreArray(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr); 998 ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr); 999 ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1000 ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1001 remove_rhs = PETSC_TRUE; 1002 } 1003 1004 /* remove the computed solution or the initial guess from the rhs */ 1005 if (remove_rhs || (ksp && pcbddc->ksp_guess_nonzero) ) { 1006 ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr); 1007 ierr = MatMultAdd(pc->pmat,used_vec,rhs,rhs);CHKERRQ(ierr); 1008 ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr); 1009 ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr); 1010 } 1011 ierr = VecDestroy(&used_vec);CHKERRQ(ierr); 1012 1013 /* store partially computed solution and set initial guess */ 1014 if (x) { 1015 ierr = VecSet(x,0.0);CHKERRQ(ierr); 1016 if (pcbddc->use_exact_dirichlet_trick) { 1017 ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1018 ierr = VecScatterEnd(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1019 ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr); 1020 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1021 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1022 if (ksp && !pcbddc->ksp_guess_nonzero) { 1023 ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr); 1024 } 1025 } 1026 } 1027 1028 if (pcbddc->ChangeOfBasisMatrix) { 1029 PCBDDCChange_ctx change_ctx; 1030 1031 /* get change ctx */ 1032 ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr); 1033 1034 /* set current iteration matrix inside change context (change of basis has been already set into the ctx during PCSetUp) */ 1035 ierr = MatDestroy(&change_ctx->original_mat);CHKERRQ(ierr); 1036 ierr = PetscObjectReference((PetscObject)pc->mat);CHKERRQ(ierr); 1037 change_ctx->original_mat = pc->mat; 1038 1039 /* change iteration matrix */ 1040 ierr = MatDestroy(&pc->mat);CHKERRQ(ierr); 1041 ierr = PetscObjectReference((PetscObject)pcbddc->new_global_mat);CHKERRQ(ierr); 1042 pc->mat = pcbddc->new_global_mat; 1043 1044 /* change rhs */ 1045 ierr = MatMultTranspose(change_ctx->global_change,rhs,pcis->vec1_global);CHKERRQ(ierr); 1046 ierr = VecCopy(pcis->vec1_global,rhs);CHKERRQ(ierr); 1047 } 1048 1049 /* remove nullspace if present */ 1050 if (ksp && x && pcbddc->NullSpace) { 1051 ierr = MatNullSpaceRemove(pcbddc->NullSpace,x);CHKERRQ(ierr); 1052 ierr = MatNullSpaceRemove(pcbddc->NullSpace,rhs);CHKERRQ(ierr); 1053 } 1054 PetscFunctionReturn(0); 1055 } 1056 1057 /* -------------------------------------------------------------------------- */ 1058 #undef __FUNCT__ 1059 #define __FUNCT__ "PCPostSolve_BDDC" 1060 /* -------------------------------------------------------------------------- */ 1061 /* 1062 PCPostSolve_BDDC - Changes the computed solution if a transformation of basis 1063 approach has been selected. Also, restores rhs to its original state. 1064 1065 Input Parameter: 1066 + pc - the preconditioner contex 1067 1068 Application Interface Routine: PCPostSolve() 1069 1070 Notes: 1071 The interface routine PCPostSolve() is not usually called directly by 1072 the user, but instead is called by KSPSolve(). 1073 */ 1074 static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x) 1075 { 1076 PetscErrorCode ierr; 1077 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 1078 1079 PetscFunctionBegin; 1080 if (pcbddc->ChangeOfBasisMatrix) { 1081 PCBDDCChange_ctx change_ctx; 1082 1083 /* get change ctx */ 1084 ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr); 1085 1086 /* restore iteration matrix */ 1087 ierr = MatDestroy(&pc->mat);CHKERRQ(ierr); 1088 ierr = PetscObjectReference((PetscObject)change_ctx->original_mat);CHKERRQ(ierr); 1089 pc->mat = change_ctx->original_mat; 1090 1091 /* get solution in original basis */ 1092 if (x) { 1093 PC_IS *pcis = (PC_IS*)(pc->data); 1094 ierr = MatMult(change_ctx->global_change,x,pcis->vec1_global);CHKERRQ(ierr); 1095 ierr = VecCopy(pcis->vec1_global,x);CHKERRQ(ierr); 1096 } 1097 } 1098 1099 /* add solution removed in presolve */ 1100 if (x) { 1101 ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr); 1102 } 1103 1104 /* restore rhs to its original state */ 1105 if (rhs) { 1106 ierr = VecCopy(pcbddc->original_rhs,rhs);CHKERRQ(ierr); 1107 } 1108 1109 /* restore ksp guess state */ 1110 if (ksp) { 1111 ierr = KSPSetInitialGuessNonzero(ksp,pcbddc->ksp_guess_nonzero);CHKERRQ(ierr); 1112 } 1113 PetscFunctionReturn(0); 1114 } 1115 /* -------------------------------------------------------------------------- */ 1116 #undef __FUNCT__ 1117 #define __FUNCT__ "PCSetUp_BDDC" 1118 /* -------------------------------------------------------------------------- */ 1119 /* 1120 PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner 1121 by setting data structures and options. 1122 1123 Input Parameter: 1124 + pc - the preconditioner context 1125 1126 Application Interface Routine: PCSetUp() 1127 1128 Notes: 1129 The interface routine PCSetUp() is not usually called directly by 1130 the user, but instead is called by PCApply() if necessary. 1131 */ 1132 PetscErrorCode PCSetUp_BDDC(PC pc) 1133 { 1134 PetscErrorCode ierr; 1135 PC_BDDC* pcbddc = (PC_BDDC*)pc->data; 1136 MatNullSpace nearnullspace; 1137 PetscBool computeis,computetopography,computesolvers; 1138 PetscBool new_nearnullspace_provided; 1139 1140 PetscFunctionBegin; 1141 /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */ 1142 /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup 1143 Also, BDDC directly build the Dirichlet problem */ 1144 /* split work */ 1145 if (pc->setupcalled) { 1146 computeis = PETSC_FALSE; 1147 if (pc->flag == SAME_NONZERO_PATTERN) { 1148 computetopography = PETSC_FALSE; 1149 computesolvers = PETSC_TRUE; 1150 } else { /* DIFFERENT_NONZERO_PATTERN */ 1151 computetopography = PETSC_TRUE; 1152 computesolvers = PETSC_TRUE; 1153 } 1154 } else { 1155 computeis = PETSC_TRUE; 1156 computetopography = PETSC_TRUE; 1157 computesolvers = PETSC_TRUE; 1158 } 1159 if (pcbddc->recompute_topography) { 1160 computetopography = PETSC_TRUE; 1161 } 1162 1163 /* Get stdout for dbg */ 1164 if (pcbddc->dbg_flag) { 1165 if (!pcbddc->dbg_viewer) { 1166 pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc)); 1167 ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr); 1168 } 1169 ierr = PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr); 1170 } 1171 1172 /* Set up all the "iterative substructuring" common block without computing solvers */ 1173 if (computeis) { 1174 /* HACK INTO PCIS */ 1175 PC_IS* pcis = (PC_IS*)pc->data; 1176 pcis->computesolvers = PETSC_FALSE; 1177 ierr = PCISSetUp(pc);CHKERRQ(ierr); 1178 ierr = ISLocalToGlobalMappingCreateIS(pcis->is_B_local,&pcbddc->BtoNmap);CHKERRQ(ierr); 1179 } 1180 1181 /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */ 1182 if (pcbddc->user_ChangeOfBasisMatrix) { 1183 pcbddc->use_change_of_basis = PETSC_FALSE; 1184 } 1185 1186 /* Analyze interface */ 1187 if (computetopography) { 1188 ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr); 1189 /* Schurs on subsets should be reset */ 1190 if (pcbddc->deluxe_ctx) { 1191 ierr = PCBDDCSubSchursReset(pcbddc->deluxe_ctx->sub_schurs);CHKERRQ(ierr); 1192 } 1193 } 1194 1195 /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */ 1196 new_nearnullspace_provided = PETSC_FALSE; 1197 ierr = MatGetNearNullSpace(pc->pmat,&nearnullspace);CHKERRQ(ierr); 1198 if (pcbddc->onearnullspace) { /* already used nearnullspace */ 1199 if (!nearnullspace) { /* near null space attached to mat has been destroyed */ 1200 new_nearnullspace_provided = PETSC_TRUE; 1201 } else { 1202 /* determine if the two nullspaces are different (should be lightweight) */ 1203 if (nearnullspace != pcbddc->onearnullspace) { 1204 new_nearnullspace_provided = PETSC_TRUE; 1205 } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */ 1206 PetscInt i; 1207 const Vec *nearnullvecs; 1208 PetscObjectState state; 1209 PetscInt nnsp_size; 1210 ierr = MatNullSpaceGetVecs(nearnullspace,NULL,&nnsp_size,&nearnullvecs);CHKERRQ(ierr); 1211 for (i=0;i<nnsp_size;i++) { 1212 ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&state);CHKERRQ(ierr); 1213 if (pcbddc->onearnullvecs_state[i] != state) { 1214 new_nearnullspace_provided = PETSC_TRUE; 1215 break; 1216 } 1217 } 1218 } 1219 } 1220 } else { 1221 if (!nearnullspace) { /* both nearnullspaces are null */ 1222 new_nearnullspace_provided = PETSC_FALSE; 1223 } else { /* nearnullspace attached later */ 1224 new_nearnullspace_provided = PETSC_TRUE; 1225 } 1226 } 1227 1228 /* Setup constraints and related work vectors */ 1229 /* reset primal space flags */ 1230 pcbddc->new_primal_space = PETSC_FALSE; 1231 pcbddc->new_primal_space_local = PETSC_FALSE; 1232 if (computetopography || new_nearnullspace_provided) { 1233 /* It also sets the primal space flags */ 1234 ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr); 1235 /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */ 1236 ierr = PCBDDCSetUpLocalWorkVectors(pc);CHKERRQ(ierr); 1237 /* Schurs on subsets should be reset */ 1238 if (pcbddc->deluxe_ctx) { 1239 ierr = PCBDDCSubSchursReset(pcbddc->deluxe_ctx->sub_schurs);CHKERRQ(ierr); 1240 } 1241 } 1242 1243 if (computesolvers || pcbddc->new_primal_space) { 1244 /* Create coarse and local stuffs */ 1245 ierr = PCBDDCSetUpSolvers(pc);CHKERRQ(ierr); 1246 /* Create scaling operators */ 1247 ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr); 1248 } 1249 1250 if (pcbddc->dbg_flag) { 1251 ierr = PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr); 1252 } 1253 PetscFunctionReturn(0); 1254 } 1255 1256 /* -------------------------------------------------------------------------- */ 1257 /* 1258 PCApply_BDDC - Applies the BDDC operator to a vector. 1259 1260 Input Parameters: 1261 . pc - the preconditioner context 1262 . r - input vector (global) 1263 1264 Output Parameter: 1265 . z - output vector (global) 1266 1267 Application Interface Routine: PCApply() 1268 */ 1269 #undef __FUNCT__ 1270 #define __FUNCT__ "PCApply_BDDC" 1271 PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z) 1272 { 1273 PC_IS *pcis = (PC_IS*)(pc->data); 1274 PC_BDDC *pcbddc = (PC_BDDC*)(pc->data); 1275 PetscErrorCode ierr; 1276 const PetscScalar one = 1.0; 1277 const PetscScalar m_one = -1.0; 1278 const PetscScalar zero = 0.0; 1279 1280 /* This code is similar to that provided in nn.c for PCNN 1281 NN interface preconditioner changed to BDDC 1282 Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static = PETSC_TRUE) */ 1283 1284 PetscFunctionBegin; 1285 if (!pcbddc->use_exact_dirichlet_trick) { 1286 /* First Dirichlet solve */ 1287 ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1288 ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1289 ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr); 1290 /* 1291 Assembling right hand side for BDDC operator 1292 - pcis->vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE) 1293 - pcis->vec1_B the interface part of the global vector z 1294 */ 1295 ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr); 1296 ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr); 1297 if (pcbddc->switch_static) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); } 1298 ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr); 1299 ierr = VecCopy(r,z);CHKERRQ(ierr); 1300 ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1301 ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1302 ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr); 1303 } else { 1304 ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr); 1305 ierr = VecSet(pcis->vec2_D,zero);CHKERRQ(ierr); 1306 ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr); 1307 } 1308 1309 /* Apply interface preconditioner 1310 input/output vecs: pcis->vec1_B and pcis->vec1_D */ 1311 ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr); 1312 1313 /* Apply transpose of partition of unity operator */ 1314 ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr); 1315 1316 /* Second Dirichlet solve and assembling of output */ 1317 ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1318 ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1319 ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr); 1320 if (pcbddc->switch_static) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); } 1321 ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr); 1322 ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr); 1323 if (pcbddc->switch_static) { ierr = VecAXPY(pcis->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); } 1324 ierr = VecAXPY(pcis->vec2_D,one,pcis->vec4_D);CHKERRQ(ierr); 1325 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1326 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1327 PetscFunctionReturn(0); 1328 } 1329 1330 /* -------------------------------------------------------------------------- */ 1331 /* 1332 PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector. 1333 1334 Input Parameters: 1335 . pc - the preconditioner context 1336 . r - input vector (global) 1337 1338 Output Parameter: 1339 . z - output vector (global) 1340 1341 Application Interface Routine: PCApplyTranspose() 1342 */ 1343 #undef __FUNCT__ 1344 #define __FUNCT__ "PCApplyTranspose_BDDC" 1345 PetscErrorCode PCApplyTranspose_BDDC(PC pc,Vec r,Vec z) 1346 { 1347 PC_IS *pcis = (PC_IS*)(pc->data); 1348 PC_BDDC *pcbddc = (PC_BDDC*)(pc->data); 1349 PetscErrorCode ierr; 1350 const PetscScalar one = 1.0; 1351 const PetscScalar m_one = -1.0; 1352 const PetscScalar zero = 0.0; 1353 1354 PetscFunctionBegin; 1355 if (!pcbddc->use_exact_dirichlet_trick) { 1356 /* First Dirichlet solve */ 1357 ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1358 ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1359 ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr); 1360 /* 1361 Assembling right hand side for BDDC operator 1362 - pcis->vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE) 1363 - pcis->vec1_B the interface part of the global vector z 1364 */ 1365 ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr); 1366 ierr = MatMultTranspose(pcis->A_IB,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr); 1367 if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); } 1368 ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr); 1369 ierr = VecCopy(r,z);CHKERRQ(ierr); 1370 ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1371 ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1372 ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr); 1373 } else { 1374 ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr); 1375 ierr = VecSet(pcis->vec2_D,zero);CHKERRQ(ierr); 1376 ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr); 1377 } 1378 1379 /* Apply interface preconditioner 1380 input/output vecs: pcis->vec1_B and pcis->vec1_D */ 1381 ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_TRUE);CHKERRQ(ierr); 1382 1383 /* Apply transpose of partition of unity operator */ 1384 ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr); 1385 1386 /* Second Dirichlet solve and assembling of output */ 1387 ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1388 ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1389 ierr = MatMultTranspose(pcis->A_BI,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr); 1390 if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); } 1391 ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr); 1392 ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr); 1393 if (pcbddc->switch_static) { ierr = VecAXPY(pcis->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); } 1394 ierr = VecAXPY(pcis->vec2_D,one,pcis->vec4_D);CHKERRQ(ierr); 1395 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1396 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1397 PetscFunctionReturn(0); 1398 } 1399 /* -------------------------------------------------------------------------- */ 1400 1401 #undef __FUNCT__ 1402 #define __FUNCT__ "PCDestroy_BDDC" 1403 PetscErrorCode PCDestroy_BDDC(PC pc) 1404 { 1405 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 1406 PetscErrorCode ierr; 1407 1408 PetscFunctionBegin; 1409 /* free data created by PCIS */ 1410 ierr = PCISDestroy(pc);CHKERRQ(ierr); 1411 /* free BDDC custom data */ 1412 ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr); 1413 /* destroy objects related to topography */ 1414 ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr); 1415 /* free allocated graph structure */ 1416 ierr = PetscFree(pcbddc->mat_graph);CHKERRQ(ierr); 1417 /* destroy objects for scaling operator */ 1418 ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr); 1419 ierr = PetscFree(pcbddc->deluxe_ctx);CHKERRQ(ierr); 1420 /* free solvers stuff */ 1421 ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr); 1422 /* free global vectors needed in presolve */ 1423 ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr); 1424 ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr); 1425 /* free stuff for change of basis hooks */ 1426 if (pcbddc->new_global_mat) { 1427 PCBDDCChange_ctx change_ctx; 1428 ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr); 1429 ierr = MatDestroy(&change_ctx->original_mat);CHKERRQ(ierr); 1430 ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr); 1431 ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr); 1432 ierr = PetscFree(change_ctx);CHKERRQ(ierr); 1433 } 1434 ierr = MatDestroy(&pcbddc->new_global_mat);CHKERRQ(ierr); 1435 /* remove map from local boundary to local numbering */ 1436 ierr = ISLocalToGlobalMappingDestroy(&pcbddc->BtoNmap);CHKERRQ(ierr); 1437 /* remove functions */ 1438 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",NULL);CHKERRQ(ierr); 1439 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr); 1440 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr); 1441 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL);CHKERRQ(ierr); 1442 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL);CHKERRQ(ierr); 1443 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL);CHKERRQ(ierr); 1444 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",NULL);CHKERRQ(ierr); 1445 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr); 1446 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr); 1447 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr); 1448 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr); 1449 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr); 1450 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr); 1451 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr); 1452 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr); 1453 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr); 1454 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",NULL);CHKERRQ(ierr); 1455 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr); 1456 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr); 1457 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr); 1458 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr); 1459 /* Free the private data structure */ 1460 ierr = PetscFree(pc->data);CHKERRQ(ierr); 1461 PetscFunctionReturn(0); 1462 } 1463 /* -------------------------------------------------------------------------- */ 1464 1465 #undef __FUNCT__ 1466 #define __FUNCT__ "PCBDDCMatFETIDPGetRHS_BDDC" 1467 static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) 1468 { 1469 FETIDPMat_ctx mat_ctx; 1470 PC_IS* pcis; 1471 PC_BDDC* pcbddc; 1472 PetscErrorCode ierr; 1473 1474 PetscFunctionBegin; 1475 ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr); 1476 pcis = (PC_IS*)mat_ctx->pc->data; 1477 pcbddc = (PC_BDDC*)mat_ctx->pc->data; 1478 1479 /* change of basis for physical rhs if needed 1480 It also changes the rhs in case of dirichlet boundaries */ 1481 ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,standard_rhs,NULL);CHKERRQ(ierr); 1482 /* store vectors for computation of fetidp final solution */ 1483 ierr = VecScatterBegin(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1484 ierr = VecScatterEnd(pcis->global_to_D,standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1485 /* scale rhs since it should be unassembled */ 1486 /* TODO use counter scaling? (also below) */ 1487 ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1488 ierr = VecScatterEnd(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1489 /* Apply partition of unity */ 1490 ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr); 1491 /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */ 1492 if (!pcbddc->switch_static) { 1493 /* compute partially subassembled Schur complement right-hand side */ 1494 ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr); 1495 ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr); 1496 ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr); 1497 ierr = VecSet(standard_rhs,0.0);CHKERRQ(ierr); 1498 ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1499 ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1500 /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */ 1501 ierr = VecScatterBegin(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1502 ierr = VecScatterEnd(pcis->global_to_B,standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1503 ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr); 1504 } 1505 /* BDDC rhs */ 1506 ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr); 1507 if (pcbddc->switch_static) { 1508 ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr); 1509 } 1510 /* apply BDDC */ 1511 ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr); 1512 /* Application of B_delta and assembling of rhs for fetidp fluxes */ 1513 ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr); 1514 ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr); 1515 ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1516 ierr = VecScatterEnd (mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1517 /* restore original rhs */ 1518 ierr = VecCopy(pcbddc->original_rhs,standard_rhs);CHKERRQ(ierr); 1519 PetscFunctionReturn(0); 1520 } 1521 1522 #undef __FUNCT__ 1523 #define __FUNCT__ "PCBDDCMatFETIDPGetRHS" 1524 /*@ 1525 PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETIDP linear system 1526 1527 Collective 1528 1529 Input Parameters: 1530 + fetidp_mat - the FETIDP matrix object obtained by calling PCBDDCCreateFETIDPOperators 1531 . standard_rhs - the right-hand side for your linear system 1532 1533 Output Parameters: 1534 - fetidp_flux_rhs - the right-hand side for the FETIDP linear system 1535 1536 Level: developer 1537 1538 Notes: 1539 1540 .seealso: PCBDDC,PCBDDCCreateFETIDPOperators 1541 @*/ 1542 PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) 1543 { 1544 FETIDPMat_ctx mat_ctx; 1545 PetscErrorCode ierr; 1546 1547 PetscFunctionBegin; 1548 ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr); 1549 ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr); 1550 PetscFunctionReturn(0); 1551 } 1552 /* -------------------------------------------------------------------------- */ 1553 1554 #undef __FUNCT__ 1555 #define __FUNCT__ "PCBDDCMatFETIDPGetSolution_BDDC" 1556 static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) 1557 { 1558 FETIDPMat_ctx mat_ctx; 1559 PC_IS* pcis; 1560 PC_BDDC* pcbddc; 1561 PetscErrorCode ierr; 1562 1563 PetscFunctionBegin; 1564 ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr); 1565 pcis = (PC_IS*)mat_ctx->pc->data; 1566 pcbddc = (PC_BDDC*)mat_ctx->pc->data; 1567 1568 /* apply B_delta^T */ 1569 ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1570 ierr = VecScatterEnd (mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1571 ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr); 1572 /* compute rhs for BDDC application */ 1573 ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr); 1574 if (pcbddc->switch_static) { 1575 ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr); 1576 } 1577 /* apply BDDC */ 1578 ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr); 1579 /* put values into standard global vector */ 1580 ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1581 ierr = VecScatterEnd (pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1582 if (!pcbddc->switch_static) { 1583 /* compute values into the interior if solved for the partially subassembled Schur complement */ 1584 ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr); 1585 ierr = VecAXPY(mat_ctx->temp_solution_D,-1.0,pcis->vec1_D);CHKERRQ(ierr); 1586 ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr); 1587 } 1588 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1589 ierr = VecScatterEnd (pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1590 /* final change of basis if needed 1591 Is also sums the dirichlet part removed during RHS assembling */ 1592 ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr); 1593 PetscFunctionReturn(0); 1594 } 1595 1596 #undef __FUNCT__ 1597 #define __FUNCT__ "PCBDDCMatFETIDPGetSolution" 1598 /*@ 1599 PCBDDCMatFETIDPGetSolution - Compute the physical solution from the solution of the FETIDP linear system 1600 1601 Collective 1602 1603 Input Parameters: 1604 + fetidp_mat - the FETIDP matrix obtained by calling PCBDDCCreateFETIDPOperators 1605 . fetidp_flux_sol - the solution of the FETIDP linear system 1606 1607 Output Parameters: 1608 - standard_sol - the solution defined on the physical domain 1609 1610 Level: developer 1611 1612 Notes: 1613 1614 .seealso: PCBDDC,PCBDDCCreateFETIDPOperators 1615 @*/ 1616 PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) 1617 { 1618 FETIDPMat_ctx mat_ctx; 1619 PetscErrorCode ierr; 1620 1621 PetscFunctionBegin; 1622 ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr); 1623 ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr); 1624 PetscFunctionReturn(0); 1625 } 1626 /* -------------------------------------------------------------------------- */ 1627 1628 extern PetscErrorCode FETIDPMatMult(Mat,Vec,Vec); 1629 extern PetscErrorCode FETIDPMatMultTranspose(Mat,Vec,Vec); 1630 extern PetscErrorCode PCBDDCDestroyFETIDPMat(Mat); 1631 extern PetscErrorCode FETIDPPCApply(PC,Vec,Vec); 1632 extern PetscErrorCode FETIDPPCApplyTranspose(PC,Vec,Vec); 1633 extern PetscErrorCode PCBDDCDestroyFETIDPPC(PC); 1634 1635 #undef __FUNCT__ 1636 #define __FUNCT__ "PCBDDCCreateFETIDPOperators_BDDC" 1637 static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, Mat *fetidp_mat, PC *fetidp_pc) 1638 { 1639 1640 FETIDPMat_ctx fetidpmat_ctx; 1641 Mat newmat; 1642 FETIDPPC_ctx fetidppc_ctx; 1643 PC newpc; 1644 MPI_Comm comm; 1645 PetscErrorCode ierr; 1646 1647 PetscFunctionBegin; 1648 ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr); 1649 /* FETIDP linear matrix */ 1650 ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr); 1651 ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr); 1652 ierr = MatCreateShell(comm,PETSC_DECIDE,PETSC_DECIDE,fetidpmat_ctx->n_lambda,fetidpmat_ctx->n_lambda,fetidpmat_ctx,&newmat);CHKERRQ(ierr); 1653 ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr); 1654 ierr = MatShellSetOperation(newmat,MATOP_MULT_TRANSPOSE,(void (*)(void))FETIDPMatMultTranspose);CHKERRQ(ierr); 1655 ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr); 1656 ierr = MatSetUp(newmat);CHKERRQ(ierr); 1657 /* FETIDP preconditioner */ 1658 ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr); 1659 ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr); 1660 ierr = PCCreate(comm,&newpc);CHKERRQ(ierr); 1661 ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr); 1662 ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr); 1663 ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr); 1664 ierr = PCShellSetApplyTranspose(newpc,FETIDPPCApplyTranspose);CHKERRQ(ierr); 1665 ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr); 1666 ierr = PCSetOperators(newpc,newmat,newmat);CHKERRQ(ierr); 1667 ierr = PCSetUp(newpc);CHKERRQ(ierr); 1668 /* return pointers for objects created */ 1669 *fetidp_mat=newmat; 1670 *fetidp_pc=newpc; 1671 PetscFunctionReturn(0); 1672 } 1673 1674 #undef __FUNCT__ 1675 #define __FUNCT__ "PCBDDCCreateFETIDPOperators" 1676 /*@ 1677 PCBDDCCreateFETIDPOperators - Create operators for FETIDP 1678 1679 Collective 1680 1681 Input Parameters: 1682 + pc - the BDDC preconditioning context already setup 1683 1684 Output Parameters: 1685 . fetidp_mat - shell FETIDP matrix object 1686 . fetidp_pc - shell Dirichlet preconditioner for FETIDP matrix 1687 1688 Options Database Keys: 1689 - -fetidp_fullyredundant: use or not a fully redundant set of Lagrange multipliers 1690 1691 Level: developer 1692 1693 Notes: 1694 Currently the only operation provided for FETIDP matrix is MatMult 1695 1696 .seealso: PCBDDC 1697 @*/ 1698 PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, Mat *fetidp_mat, PC *fetidp_pc) 1699 { 1700 PetscErrorCode ierr; 1701 1702 PetscFunctionBegin; 1703 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1704 if (pc->setupcalled) { 1705 ierr = PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,Mat*,PC*),(pc,fetidp_mat,fetidp_pc));CHKERRQ(ierr); 1706 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"You must call PCSetup_BDDC() first \n"); 1707 PetscFunctionReturn(0); 1708 } 1709 /* -------------------------------------------------------------------------- */ 1710 /*MC 1711 PCBDDC - Balancing Domain Decomposition by Constraints. 1712 1713 An implementation of the BDDC preconditioner based on 1714 1715 .vb 1716 [1] C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007 1717 [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 1718 [3] J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", http://arxiv.org/abs/0712.3977 1719 .ve 1720 1721 The matrix to be preconditioned (Pmat) must be of type MATIS. 1722 1723 Currently works with MATIS matrices with local Neumann matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers. 1724 1725 It also works with unsymmetric and indefinite problems. 1726 1727 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. 1728 1729 Approximate local solvers are automatically adapted for singular linear problems (see [1]) if the user has provided the nullspace using PCBDDCSetNullSpace 1730 1731 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() 1732 1733 Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). 1734 1735 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. 1736 1737 The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using MatPartitioning object. 1738 1739 Options Database Keys: 1740 1741 . -pc_bddc_use_vertices <1> - use or not vertices in primal space 1742 . -pc_bddc_use_edges <1> - use or not edges in primal space 1743 . -pc_bddc_use_faces <0> - use or not faces in primal space 1744 . -pc_bddc_use_change_of_basis <0> - use change of basis approach (on edges only) 1745 . -pc_bddc_use_change_on_faces <0> - use change of basis approach on faces if change of basis has been requested 1746 . -pc_bddc_switch_static <0> - switches from M_2 to M_3 operator (see reference article [1]) 1747 . -pc_bddc_levels <0> - maximum number of levels for multilevel 1748 . -pc_bddc_coarsening_ratio - H/h ratio at the coarser level 1749 - -pc_bddc_check_level <0> - set verbosity level of debugging output 1750 1751 Options for Dirichlet, Neumann or coarse solver can be set with 1752 .vb 1753 -pc_bddc_dirichlet_ 1754 -pc_bddc_neumann_ 1755 -pc_bddc_coarse_ 1756 .ve 1757 e.g -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg 1758 1759 When using a multilevel approach, solvers' options at the N-th level can be specified as 1760 .vb 1761 -pc_bddc_dirichlet_lN_ 1762 -pc_bddc_neumann_lN_ 1763 -pc_bddc_coarse_lN_ 1764 .ve 1765 Note that level number ranges from the finest 0 to the coarsest N. 1766 1767 Level: intermediate 1768 1769 Developer notes: 1770 1771 New deluxe scaling operator will be available soon. 1772 1773 Contributed by Stefano Zampini 1774 1775 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, MATIS 1776 M*/ 1777 1778 #undef __FUNCT__ 1779 #define __FUNCT__ "PCCreate_BDDC" 1780 PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc) 1781 { 1782 PetscErrorCode ierr; 1783 PC_BDDC *pcbddc; 1784 1785 PetscFunctionBegin; 1786 /* Creates the private data structure for this preconditioner and attach it to the PC object. */ 1787 ierr = PetscNewLog(pc,&pcbddc);CHKERRQ(ierr); 1788 pc->data = (void*)pcbddc; 1789 1790 /* create PCIS data structure */ 1791 ierr = PCISCreate(pc);CHKERRQ(ierr); 1792 1793 /* BDDC customization */ 1794 pcbddc->use_local_adj = PETSC_TRUE; 1795 pcbddc->use_vertices = PETSC_TRUE; 1796 pcbddc->use_edges = PETSC_TRUE; 1797 pcbddc->use_faces = PETSC_FALSE; 1798 pcbddc->use_change_of_basis = PETSC_FALSE; 1799 pcbddc->use_change_on_faces = PETSC_FALSE; 1800 pcbddc->switch_static = PETSC_FALSE; 1801 pcbddc->use_nnsp_true = PETSC_FALSE; /* not yet exposed */ 1802 pcbddc->dbg_flag = 0; 1803 /* private */ 1804 pcbddc->issym = PETSC_FALSE; 1805 pcbddc->BtoNmap = 0; 1806 pcbddc->local_primal_size = 0; 1807 pcbddc->n_vertices = 0; 1808 pcbddc->n_actual_vertices = 0; 1809 pcbddc->n_constraints = 0; 1810 pcbddc->primal_indices_local_idxs = 0; 1811 pcbddc->recompute_topography = PETSC_FALSE; 1812 pcbddc->coarse_size = -1; 1813 pcbddc->new_primal_space = PETSC_FALSE; 1814 pcbddc->new_primal_space_local = PETSC_FALSE; 1815 pcbddc->global_primal_indices = 0; 1816 pcbddc->onearnullspace = 0; 1817 pcbddc->onearnullvecs_state = 0; 1818 pcbddc->user_primal_vertices = 0; 1819 pcbddc->NullSpace = 0; 1820 pcbddc->temp_solution = 0; 1821 pcbddc->original_rhs = 0; 1822 pcbddc->local_mat = 0; 1823 pcbddc->ChangeOfBasisMatrix = 0; 1824 pcbddc->user_ChangeOfBasisMatrix = 0; 1825 pcbddc->new_global_mat = 0; 1826 pcbddc->coarse_vec = 0; 1827 pcbddc->coarse_rhs = 0; 1828 pcbddc->coarse_ksp = 0; 1829 pcbddc->coarse_phi_B = 0; 1830 pcbddc->coarse_phi_D = 0; 1831 pcbddc->coarse_psi_B = 0; 1832 pcbddc->coarse_psi_D = 0; 1833 pcbddc->vec1_P = 0; 1834 pcbddc->vec1_R = 0; 1835 pcbddc->vec2_R = 0; 1836 pcbddc->local_auxmat1 = 0; 1837 pcbddc->local_auxmat2 = 0; 1838 pcbddc->R_to_B = 0; 1839 pcbddc->R_to_D = 0; 1840 pcbddc->ksp_D = 0; 1841 pcbddc->ksp_R = 0; 1842 pcbddc->NeumannBoundaries = 0; 1843 pcbddc->NeumannBoundariesLocal = 0; 1844 pcbddc->DirichletBoundaries = 0; 1845 pcbddc->DirichletBoundariesLocal = 0; 1846 pcbddc->user_provided_isfordofs = PETSC_FALSE; 1847 pcbddc->n_ISForDofs = 0; 1848 pcbddc->n_ISForDofsLocal = 0; 1849 pcbddc->ISForDofs = 0; 1850 pcbddc->ISForDofsLocal = 0; 1851 pcbddc->ConstraintMatrix = 0; 1852 pcbddc->use_exact_dirichlet_trick = PETSC_TRUE; 1853 pcbddc->coarse_loc_to_glob = 0; 1854 pcbddc->coarsening_ratio = 8; 1855 pcbddc->current_level = 0; 1856 pcbddc->max_levels = 0; 1857 pcbddc->use_coarse_estimates = PETSC_FALSE; 1858 pcbddc->coarse_subassembling = 0; 1859 pcbddc->coarse_subassembling_init = 0; 1860 1861 /* create local graph structure */ 1862 ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr); 1863 1864 /* scaling */ 1865 pcbddc->work_scaling = 0; 1866 pcbddc->use_deluxe_scaling = PETSC_FALSE; 1867 pcbddc->deluxe_threshold = 1; 1868 pcbddc->deluxe_rebuild = PETSC_FALSE; 1869 pcbddc->deluxe_layers = -1; 1870 pcbddc->deluxe_use_useradj = PETSC_FALSE; 1871 pcbddc->deluxe_compute_rowadj = PETSC_TRUE; 1872 1873 /* function pointers */ 1874 pc->ops->apply = PCApply_BDDC; 1875 pc->ops->applytranspose = PCApplyTranspose_BDDC; 1876 pc->ops->setup = PCSetUp_BDDC; 1877 pc->ops->destroy = PCDestroy_BDDC; 1878 pc->ops->setfromoptions = PCSetFromOptions_BDDC; 1879 pc->ops->view = 0; 1880 pc->ops->applyrichardson = 0; 1881 pc->ops->applysymmetricleft = 0; 1882 pc->ops->applysymmetricright = 0; 1883 pc->ops->presolve = PCPreSolve_BDDC; 1884 pc->ops->postsolve = PCPostSolve_BDDC; 1885 1886 /* composing function */ 1887 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",PCBDDCSetChangeOfBasisMat_BDDC);CHKERRQ(ierr); 1888 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr); 1889 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr); 1890 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC);CHKERRQ(ierr); 1891 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC);CHKERRQ(ierr); 1892 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC);CHKERRQ(ierr); 1893 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",PCBDDCSetNullSpace_BDDC);CHKERRQ(ierr); 1894 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr); 1895 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",PCBDDCSetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr); 1896 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr); 1897 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",PCBDDCSetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr); 1898 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr); 1899 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",PCBDDCGetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr); 1900 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr); 1901 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",PCBDDCGetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr); 1902 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr); 1903 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",PCBDDCSetDofsSplittingLocal_BDDC);CHKERRQ(ierr); 1904 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr); 1905 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr); 1906 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr); 1907 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr); 1908 PetscFunctionReturn(0); 1909 } 1910 1911