1 /* TODOLIST 2 3 Solvers 4 - Add support for cholesky for coarse solver (similar to local solvers) 5 - Propagate ksp prefixes for solvers to mat objects? 6 7 User interface 8 - ** DM attached to pc? 9 10 Debugging output 11 - * Better management of verbosity levels of debugging output 12 13 Extra 14 - *** Is it possible to work with PCBDDCGraph on boundary indices only (less memory consumed)? 15 - BDDC with MG framework? 16 17 FETIDP 18 - Move FETIDP code to its own classes 19 20 MATIS related operations contained in BDDC code 21 - Provide general case for subassembling 22 23 */ 24 25 #include <../src/ksp/pc/impls/bddc/bddc.h> /*I "petscpc.h" I*/ /* includes for fortran wrappers */ 26 #include <../src/ksp/pc/impls/bddc/bddcprivate.h> 27 #include <petscblaslapack.h> 28 29 /* temporarily declare it */ 30 PetscErrorCode PCApply_BDDC(PC,Vec,Vec); 31 32 /* -------------------------------------------------------------------------- */ 33 #undef __FUNCT__ 34 #define __FUNCT__ "PCSetFromOptions_BDDC" 35 PetscErrorCode PCSetFromOptions_BDDC(PetscOptions *PetscOptionsObject,PC pc) 36 { 37 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 38 PetscErrorCode ierr; 39 40 PetscFunctionBegin; 41 ierr = PetscOptionsHead(PetscOptionsObject,"BDDC options");CHKERRQ(ierr); 42 /* Verbose debugging */ 43 ierr = PetscOptionsInt("-pc_bddc_check_level","Verbose output for PCBDDC (intended for debug)","none",pcbddc->dbg_flag,&pcbddc->dbg_flag,NULL);CHKERRQ(ierr); 44 /* Primal space cumstomization */ 45 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); 46 ierr = PetscOptionsBool("-pc_bddc_use_vertices","Use or not corner dofs in coarse space","none",pcbddc->use_vertices,&pcbddc->use_vertices,NULL);CHKERRQ(ierr); 47 ierr = PetscOptionsBool("-pc_bddc_use_edges","Use or not edge constraints in coarse space","none",pcbddc->use_edges,&pcbddc->use_edges,NULL);CHKERRQ(ierr); 48 ierr = PetscOptionsBool("-pc_bddc_use_faces","Use or not face constraints in coarse space","none",pcbddc->use_faces,&pcbddc->use_faces,NULL);CHKERRQ(ierr); 49 ierr = PetscOptionsBool("-pc_bddc_use_true_nnsp","Use near null space attached to the matrix without modifications","none",pcbddc->use_nnsp_true,&pcbddc->use_nnsp_true,NULL);CHKERRQ(ierr); 50 ierr = PetscOptionsBool("-pc_bddc_use_qr_single","Use QR factorization for single constraints on cc (QR is used when multiple constraints are present)","none",pcbddc->use_qr_single,&pcbddc->use_qr_single,NULL);CHKERRQ(ierr); 51 /* Change of basis */ 52 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); 53 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); 54 if (!pcbddc->use_change_of_basis) { 55 pcbddc->use_change_on_faces = PETSC_FALSE; 56 } 57 /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */ 58 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); 59 ierr = PetscOptionsInt("-pc_bddc_coarse_redistribute","Number of procs where to redistribute coarse problem","none",pcbddc->redistribute_coarse,&pcbddc->redistribute_coarse,NULL);CHKERRQ(ierr); 60 ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","none",pcbddc->coarsening_ratio,&pcbddc->coarsening_ratio,NULL);CHKERRQ(ierr); 61 ierr = PetscOptionsInt("-pc_bddc_levels","Set maximum number of levels for multilevel","none",pcbddc->max_levels,&pcbddc->max_levels,NULL);CHKERRQ(ierr); 62 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); 63 ierr = PetscOptionsBool("-pc_bddc_use_deluxe_scaling","Use deluxe scaling for BDDC","none",pcbddc->use_deluxe_scaling,&pcbddc->use_deluxe_scaling,NULL);CHKERRQ(ierr); 64 ierr = PetscOptionsBool("-pc_bddc_schur_rebuild","Whether or not the interface graph for Schur principal minors has to be rebuilt (i.e. define the interface without any adjacency)","none",pcbddc->sub_schurs_rebuild,&pcbddc->sub_schurs_rebuild,NULL);CHKERRQ(ierr); 65 ierr = PetscOptionsInt("-pc_bddc_schur_layers","Number of dofs' layers for the computation of principal minors (i.e. -1 uses all dofs)","none",pcbddc->sub_schurs_layers,&pcbddc->sub_schurs_layers,NULL);CHKERRQ(ierr); 66 ierr = PetscOptionsBool("-pc_bddc_schur_use_useradj","Whether or not the CSR graph specified by the user should be used for computing successive layers (default is to use adj of local mat)","none",pcbddc->sub_schurs_use_useradj,&pcbddc->sub_schurs_use_useradj,NULL);CHKERRQ(ierr); 67 ierr = PetscOptionsBool("-pc_bddc_deluxe_faster","Faster application of deluxe scaling (requires extra work during setup)","none",pcbddc->faster_deluxe,&pcbddc->faster_deluxe,NULL);CHKERRQ(ierr); 68 ierr = PetscOptionsReal("-pc_bddc_adaptive_threshold","Threshold to be used for adaptive selection of constraints","none",pcbddc->adaptive_threshold,&pcbddc->adaptive_threshold,NULL);CHKERRQ(ierr); 69 ierr = PetscOptionsInt("-pc_bddc_adaptive_nmin","Minimum number of constraints per connected components","none",pcbddc->adaptive_nmin,&pcbddc->adaptive_nmin,NULL);CHKERRQ(ierr); 70 ierr = PetscOptionsInt("-pc_bddc_adaptive_nmax","Maximum number of constraints per connected components","none",pcbddc->adaptive_nmax,&pcbddc->adaptive_nmax,NULL);CHKERRQ(ierr); 71 ierr = PetscOptionsBool("-pc_bddc_symmetric","Symmetric computation of primal basis functions","none",pcbddc->symmetric_primal,&pcbddc->symmetric_primal,NULL);CHKERRQ(ierr); 72 ierr = PetscOptionsInt("-pc_bddc_coarse_adj","Number of processors where to map the coarse adjacency list","none",pcbddc->coarse_adj_red,&pcbddc->coarse_adj_red,NULL);CHKERRQ(ierr); 73 ierr = PetscOptionsBool("-pc_bddc_benign_trick","Apply the benign subspace trick to a class of saddle point problems","none",pcbddc->benign_saddle_point,&pcbddc->benign_saddle_point,NULL);CHKERRQ(ierr); 74 ierr = PetscOptionsTail();CHKERRQ(ierr); 75 PetscFunctionReturn(0); 76 } 77 /* -------------------------------------------------------------------------- */ 78 #undef __FUNCT__ 79 #define __FUNCT__ "PCBDDCSetChangeOfBasisMat_BDDC" 80 static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change) 81 { 82 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 83 PetscErrorCode ierr; 84 85 PetscFunctionBegin; 86 ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr); 87 ierr = PetscObjectReference((PetscObject)change);CHKERRQ(ierr); 88 pcbddc->user_ChangeOfBasisMatrix = change; 89 PetscFunctionReturn(0); 90 } 91 #undef __FUNCT__ 92 #define __FUNCT__ "PCBDDCSetChangeOfBasisMat" 93 /*@ 94 PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs 95 96 Collective on PC 97 98 Input Parameters: 99 + pc - the preconditioning context 100 - change - the change of basis matrix 101 102 Level: intermediate 103 104 Notes: 105 106 .seealso: PCBDDC 107 @*/ 108 PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change) 109 { 110 PetscErrorCode ierr; 111 112 PetscFunctionBegin; 113 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 114 PetscValidHeaderSpecific(change,MAT_CLASSID,2); 115 PetscCheckSameComm(pc,1,change,2); 116 if (pc->mat) { 117 PetscInt rows_c,cols_c,rows,cols; 118 ierr = MatGetSize(pc->mat,&rows,&cols);CHKERRQ(ierr); 119 ierr = MatGetSize(change,&rows_c,&cols_c);CHKERRQ(ierr); 120 if (rows_c != rows) { 121 SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of rows for change of basis matrix! %d != %d",rows_c,rows); 122 } 123 if (cols_c != cols) { 124 SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of columns for change of basis matrix! %d != %d",cols_c,cols); 125 } 126 ierr = MatGetLocalSize(pc->mat,&rows,&cols);CHKERRQ(ierr); 127 ierr = MatGetLocalSize(change,&rows_c,&cols_c);CHKERRQ(ierr); 128 if (rows_c != rows) { 129 SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of local rows for change of basis matrix! %d != %d",rows_c,rows); 130 } 131 if (cols_c != cols) { 132 SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of local columns for change of basis matrix! %d != %d",cols_c,cols); 133 } 134 } 135 ierr = PetscTryMethod(pc,"PCBDDCSetChangeOfBasisMat_C",(PC,Mat),(pc,change));CHKERRQ(ierr); 136 PetscFunctionReturn(0); 137 } 138 /* -------------------------------------------------------------------------- */ 139 #undef __FUNCT__ 140 #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS_BDDC" 141 static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices) 142 { 143 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 144 PetscErrorCode ierr; 145 146 PetscFunctionBegin; 147 ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr); 148 ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr); 149 pcbddc->user_primal_vertices = PrimalVertices; 150 PetscFunctionReturn(0); 151 } 152 #undef __FUNCT__ 153 #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS" 154 /*@ 155 PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in PCBDDC 156 157 Collective 158 159 Input Parameters: 160 + pc - the preconditioning context 161 - PrimalVertices - index set of primal vertices in local numbering (can be empty) 162 163 Level: intermediate 164 165 Notes: 166 167 .seealso: PCBDDC 168 @*/ 169 PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices) 170 { 171 PetscErrorCode ierr; 172 173 PetscFunctionBegin; 174 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 175 PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2); 176 PetscCheckSameComm(pc,1,PrimalVertices,2); 177 ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr); 178 PetscFunctionReturn(0); 179 } 180 /* -------------------------------------------------------------------------- */ 181 #undef __FUNCT__ 182 #define __FUNCT__ "PCBDDCSetCoarseningRatio_BDDC" 183 static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k) 184 { 185 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 186 187 PetscFunctionBegin; 188 pcbddc->coarsening_ratio = k; 189 PetscFunctionReturn(0); 190 } 191 192 #undef __FUNCT__ 193 #define __FUNCT__ "PCBDDCSetCoarseningRatio" 194 /*@ 195 PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel 196 197 Logically collective on PC 198 199 Input Parameters: 200 + pc - the preconditioning context 201 - k - coarsening ratio (H/h at the coarser level) 202 203 Options Database Keys: 204 . -pc_bddc_coarsening_ratio 205 206 Level: intermediate 207 208 Notes: 209 Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level 210 211 .seealso: PCBDDC, PCBDDCSetLevels() 212 @*/ 213 PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k) 214 { 215 PetscErrorCode ierr; 216 217 PetscFunctionBegin; 218 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 219 PetscValidLogicalCollectiveInt(pc,k,2); 220 ierr = PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));CHKERRQ(ierr); 221 PetscFunctionReturn(0); 222 } 223 224 /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */ 225 #undef __FUNCT__ 226 #define __FUNCT__ "PCBDDCSetUseExactDirichlet_BDDC" 227 static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc,PetscBool flg) 228 { 229 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 230 231 PetscFunctionBegin; 232 pcbddc->use_exact_dirichlet_trick = flg; 233 PetscFunctionReturn(0); 234 } 235 236 #undef __FUNCT__ 237 #define __FUNCT__ "PCBDDCSetUseExactDirichlet" 238 PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool flg) 239 { 240 PetscErrorCode ierr; 241 242 PetscFunctionBegin; 243 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 244 PetscValidLogicalCollectiveBool(pc,flg,2); 245 ierr = PetscTryMethod(pc,"PCBDDCSetUseExactDirichlet_C",(PC,PetscBool),(pc,flg));CHKERRQ(ierr); 246 PetscFunctionReturn(0); 247 } 248 249 #undef __FUNCT__ 250 #define __FUNCT__ "PCBDDCSetLevel_BDDC" 251 static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc,PetscInt level) 252 { 253 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 254 255 PetscFunctionBegin; 256 pcbddc->current_level = level; 257 PetscFunctionReturn(0); 258 } 259 260 #undef __FUNCT__ 261 #define __FUNCT__ "PCBDDCSetLevel" 262 PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level) 263 { 264 PetscErrorCode ierr; 265 266 PetscFunctionBegin; 267 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 268 PetscValidLogicalCollectiveInt(pc,level,2); 269 ierr = PetscTryMethod(pc,"PCBDDCSetLevel_C",(PC,PetscInt),(pc,level));CHKERRQ(ierr); 270 PetscFunctionReturn(0); 271 } 272 273 #undef __FUNCT__ 274 #define __FUNCT__ "PCBDDCSetLevels_BDDC" 275 static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc,PetscInt levels) 276 { 277 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 278 279 PetscFunctionBegin; 280 pcbddc->max_levels = levels; 281 PetscFunctionReturn(0); 282 } 283 284 #undef __FUNCT__ 285 #define __FUNCT__ "PCBDDCSetLevels" 286 /*@ 287 PCBDDCSetLevels - Sets the maximum number of levels for multilevel 288 289 Logically collective on PC 290 291 Input Parameters: 292 + pc - the preconditioning context 293 - levels - the maximum number of levels (max 9) 294 295 Options Database Keys: 296 . -pc_bddc_levels 297 298 Level: intermediate 299 300 Notes: 301 Default value is 0, i.e. traditional one-level BDDC 302 303 .seealso: PCBDDC, PCBDDCSetCoarseningRatio() 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: 393 Provide the information if you used MatZeroRows/Columns routines. Any process can list any global node 394 395 .seealso: PCBDDC, PCBDDCSetDirichletBoundariesLocal(), MatZeroRows(), MatZeroRowsColumns() 396 @*/ 397 PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries) 398 { 399 PetscErrorCode ierr; 400 401 PetscFunctionBegin; 402 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 403 PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2); 404 PetscCheckSameComm(pc,1,DirichletBoundaries,2); 405 ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr); 406 PetscFunctionReturn(0); 407 } 408 /* -------------------------------------------------------------------------- */ 409 410 #undef __FUNCT__ 411 #define __FUNCT__ "PCBDDCSetDirichletBoundariesLocal_BDDC" 412 static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc,IS DirichletBoundaries) 413 { 414 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 415 PetscErrorCode ierr; 416 417 PetscFunctionBegin; 418 /* last user setting takes precendence -> destroy any other customization */ 419 ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr); 420 ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr); 421 ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr); 422 pcbddc->DirichletBoundariesLocal = DirichletBoundaries; 423 pcbddc->recompute_topography = PETSC_TRUE; 424 PetscFunctionReturn(0); 425 } 426 427 #undef __FUNCT__ 428 #define __FUNCT__ "PCBDDCSetDirichletBoundariesLocal" 429 /*@ 430 PCBDDCSetDirichletBoundariesLocal - Set IS defining Dirichlet boundaries for the global problem in local ordering. 431 432 Collective 433 434 Input Parameters: 435 + pc - the preconditioning context 436 - DirichletBoundaries - parallel IS defining the Dirichlet boundaries (in local ordering) 437 438 Level: intermediate 439 440 Notes: 441 442 .seealso: PCBDDC, PCBDDCSetDirichletBoundaries(), MatZeroRows(), MatZeroRowsColumns() 443 @*/ 444 PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc,IS DirichletBoundaries) 445 { 446 PetscErrorCode ierr; 447 448 PetscFunctionBegin; 449 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 450 PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2); 451 PetscCheckSameComm(pc,1,DirichletBoundaries,2); 452 ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundariesLocal_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr); 453 PetscFunctionReturn(0); 454 } 455 /* -------------------------------------------------------------------------- */ 456 457 #undef __FUNCT__ 458 #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC" 459 static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries) 460 { 461 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 462 PetscErrorCode ierr; 463 464 PetscFunctionBegin; 465 /* last user setting takes precendence -> destroy any other customization */ 466 ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr); 467 ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr); 468 ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr); 469 pcbddc->NeumannBoundaries = NeumannBoundaries; 470 pcbddc->recompute_topography = PETSC_TRUE; 471 PetscFunctionReturn(0); 472 } 473 474 #undef __FUNCT__ 475 #define __FUNCT__ "PCBDDCSetNeumannBoundaries" 476 /*@ 477 PCBDDCSetNeumannBoundaries - Set IS defining Neumann boundaries for the global problem. 478 479 Collective 480 481 Input Parameters: 482 + pc - the preconditioning context 483 - NeumannBoundaries - parallel IS defining the Neumann boundaries 484 485 Level: intermediate 486 487 Notes: 488 Any process can list any global node 489 490 .seealso: PCBDDC, PCBDDCSetNeumannBoundariesLocal() 491 @*/ 492 PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries) 493 { 494 PetscErrorCode ierr; 495 496 PetscFunctionBegin; 497 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 498 PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2); 499 PetscCheckSameComm(pc,1,NeumannBoundaries,2); 500 ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr); 501 PetscFunctionReturn(0); 502 } 503 /* -------------------------------------------------------------------------- */ 504 505 #undef __FUNCT__ 506 #define __FUNCT__ "PCBDDCSetNeumannBoundariesLocal_BDDC" 507 static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc,IS NeumannBoundaries) 508 { 509 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 510 PetscErrorCode ierr; 511 512 PetscFunctionBegin; 513 /* last user setting takes precendence -> destroy any other customization */ 514 ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr); 515 ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr); 516 ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr); 517 pcbddc->NeumannBoundariesLocal = NeumannBoundaries; 518 pcbddc->recompute_topography = PETSC_TRUE; 519 PetscFunctionReturn(0); 520 } 521 522 #undef __FUNCT__ 523 #define __FUNCT__ "PCBDDCSetNeumannBoundariesLocal" 524 /*@ 525 PCBDDCSetNeumannBoundariesLocal - Set IS defining Neumann boundaries for the global problem in local ordering. 526 527 Collective 528 529 Input Parameters: 530 + pc - the preconditioning context 531 - NeumannBoundaries - parallel IS defining the subdomain part of Neumann boundaries (in local ordering) 532 533 Level: intermediate 534 535 Notes: 536 537 .seealso: PCBDDC, PCBDDCSetNeumannBoundaries() 538 @*/ 539 PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc,IS NeumannBoundaries) 540 { 541 PetscErrorCode ierr; 542 543 PetscFunctionBegin; 544 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 545 PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2); 546 PetscCheckSameComm(pc,1,NeumannBoundaries,2); 547 ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundariesLocal_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr); 548 PetscFunctionReturn(0); 549 } 550 /* -------------------------------------------------------------------------- */ 551 552 #undef __FUNCT__ 553 #define __FUNCT__ "PCBDDCGetDirichletBoundaries_BDDC" 554 static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries) 555 { 556 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 557 558 PetscFunctionBegin; 559 *DirichletBoundaries = pcbddc->DirichletBoundaries; 560 PetscFunctionReturn(0); 561 } 562 563 #undef __FUNCT__ 564 #define __FUNCT__ "PCBDDCGetDirichletBoundaries" 565 /*@ 566 PCBDDCGetDirichletBoundaries - Get parallel IS for Dirichlet boundaries 567 568 Collective 569 570 Input Parameters: 571 . pc - the preconditioning context 572 573 Output Parameters: 574 . DirichletBoundaries - index set defining the Dirichlet boundaries 575 576 Level: intermediate 577 578 Notes: 579 The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetDirichletBoundaries 580 581 .seealso: PCBDDC 582 @*/ 583 PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries) 584 { 585 PetscErrorCode ierr; 586 587 PetscFunctionBegin; 588 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 589 ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr); 590 PetscFunctionReturn(0); 591 } 592 /* -------------------------------------------------------------------------- */ 593 594 #undef __FUNCT__ 595 #define __FUNCT__ "PCBDDCGetDirichletBoundariesLocal_BDDC" 596 static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc,IS *DirichletBoundaries) 597 { 598 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 599 600 PetscFunctionBegin; 601 *DirichletBoundaries = pcbddc->DirichletBoundariesLocal; 602 PetscFunctionReturn(0); 603 } 604 605 #undef __FUNCT__ 606 #define __FUNCT__ "PCBDDCGetDirichletBoundariesLocal" 607 /*@ 608 PCBDDCGetDirichletBoundariesLocal - Get parallel IS for Dirichlet boundaries (in local ordering) 609 610 Collective 611 612 Input Parameters: 613 . pc - the preconditioning context 614 615 Output Parameters: 616 . DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries 617 618 Level: intermediate 619 620 Notes: 621 The IS returned could be the same passed in earlier by the user (if provided with PCBDDCSetDirichletBoundariesLocal) or a global-to-local map of the global IS (if provided with PCBDDCSetDirichletBoundaries). 622 In the latter case, the IS will be available after PCSetUp. 623 624 .seealso: PCBDDC 625 @*/ 626 PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc,IS *DirichletBoundaries) 627 { 628 PetscErrorCode ierr; 629 630 PetscFunctionBegin; 631 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 632 ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundariesLocal_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr); 633 PetscFunctionReturn(0); 634 } 635 /* -------------------------------------------------------------------------- */ 636 637 #undef __FUNCT__ 638 #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC" 639 static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries) 640 { 641 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 642 643 PetscFunctionBegin; 644 *NeumannBoundaries = pcbddc->NeumannBoundaries; 645 PetscFunctionReturn(0); 646 } 647 648 #undef __FUNCT__ 649 #define __FUNCT__ "PCBDDCGetNeumannBoundaries" 650 /*@ 651 PCBDDCGetNeumannBoundaries - Get parallel IS for Neumann boundaries 652 653 Collective 654 655 Input Parameters: 656 . pc - the preconditioning context 657 658 Output Parameters: 659 . NeumannBoundaries - index set defining the Neumann boundaries 660 661 Level: intermediate 662 663 Notes: 664 The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetNeumannBoundaries 665 666 .seealso: PCBDDC 667 @*/ 668 PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries) 669 { 670 PetscErrorCode ierr; 671 672 PetscFunctionBegin; 673 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 674 ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr); 675 PetscFunctionReturn(0); 676 } 677 /* -------------------------------------------------------------------------- */ 678 679 #undef __FUNCT__ 680 #define __FUNCT__ "PCBDDCGetNeumannBoundariesLocal_BDDC" 681 static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc,IS *NeumannBoundaries) 682 { 683 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 684 685 PetscFunctionBegin; 686 *NeumannBoundaries = pcbddc->NeumannBoundariesLocal; 687 PetscFunctionReturn(0); 688 } 689 690 #undef __FUNCT__ 691 #define __FUNCT__ "PCBDDCGetNeumannBoundariesLocal" 692 /*@ 693 PCBDDCGetNeumannBoundariesLocal - Get parallel IS for Neumann boundaries (in local ordering) 694 695 Collective 696 697 Input Parameters: 698 . pc - the preconditioning context 699 700 Output Parameters: 701 . NeumannBoundaries - index set defining the subdomain part of Neumann boundaries 702 703 Level: intermediate 704 705 Notes: 706 The IS returned could be the same passed in earlier by the user (if provided with PCBDDCSetNeumannBoundariesLocal) or a global-to-local map of the global IS (if provided with PCBDDCSetNeumannBoundaries). 707 In the latter case, the IS will be available after PCSetUp. 708 709 .seealso: PCBDDC 710 @*/ 711 PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc,IS *NeumannBoundaries) 712 { 713 PetscErrorCode ierr; 714 715 PetscFunctionBegin; 716 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 717 ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundariesLocal_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr); 718 PetscFunctionReturn(0); 719 } 720 /* -------------------------------------------------------------------------- */ 721 722 #undef __FUNCT__ 723 #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph_BDDC" 724 static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode) 725 { 726 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 727 PCBDDCGraph mat_graph = pcbddc->mat_graph; 728 PetscErrorCode ierr; 729 730 PetscFunctionBegin; 731 /* free old CSR */ 732 ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr); 733 /* TODO: PCBDDCGraphSetAdjacency */ 734 /* get CSR into graph structure */ 735 if (copymode == PETSC_COPY_VALUES) { 736 ierr = PetscMalloc1(nvtxs+1,&mat_graph->xadj);CHKERRQ(ierr); 737 ierr = PetscMalloc1(xadj[nvtxs],&mat_graph->adjncy);CHKERRQ(ierr); 738 ierr = PetscMemcpy(mat_graph->xadj,xadj,(nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr); 739 ierr = PetscMemcpy(mat_graph->adjncy,adjncy,xadj[nvtxs]*sizeof(PetscInt));CHKERRQ(ierr); 740 } else if (copymode == PETSC_OWN_POINTER) { 741 mat_graph->xadj = (PetscInt*)xadj; 742 mat_graph->adjncy = (PetscInt*)adjncy; 743 } 744 mat_graph->nvtxs_csr = nvtxs; 745 PetscFunctionReturn(0); 746 } 747 748 #undef __FUNCT__ 749 #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph" 750 /*@ 751 PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local matrix 752 753 Not collective 754 755 Input Parameters: 756 + pc - the preconditioning context 757 . nvtxs - number of local vertices of the graph (i.e., the size of the local problem) 758 . xadj, adjncy - the CSR graph 759 - copymode - either PETSC_COPY_VALUES or PETSC_OWN_POINTER. 760 761 Level: intermediate 762 763 Notes: 764 765 .seealso: PCBDDC,PetscCopyMode 766 @*/ 767 PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode) 768 { 769 void (*f)(void) = 0; 770 PetscErrorCode ierr; 771 772 PetscFunctionBegin; 773 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 774 PetscValidIntPointer(xadj,3); 775 PetscValidIntPointer(adjncy,4); 776 if (copymode != PETSC_COPY_VALUES && copymode != PETSC_OWN_POINTER) { 777 SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %d in %s\n",copymode,__FUNCT__); 778 } 779 ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr); 780 /* free arrays if PCBDDC is not the PC type */ 781 ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr); 782 if (!f && copymode == PETSC_OWN_POINTER) { 783 ierr = PetscFree(xadj);CHKERRQ(ierr); 784 ierr = PetscFree(adjncy);CHKERRQ(ierr); 785 } 786 PetscFunctionReturn(0); 787 } 788 /* -------------------------------------------------------------------------- */ 789 790 #undef __FUNCT__ 791 #define __FUNCT__ "PCBDDCSetDofsSplittingLocal_BDDC" 792 static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc,PetscInt n_is, IS ISForDofs[]) 793 { 794 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 795 PetscInt i; 796 PetscErrorCode ierr; 797 798 PetscFunctionBegin; 799 /* Destroy ISes if they were already set */ 800 for (i=0;i<pcbddc->n_ISForDofsLocal;i++) { 801 ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr); 802 } 803 ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr); 804 /* last user setting takes precendence -> destroy any other customization */ 805 for (i=0;i<pcbddc->n_ISForDofs;i++) { 806 ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr); 807 } 808 ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr); 809 pcbddc->n_ISForDofs = 0; 810 /* allocate space then set */ 811 if (n_is) { 812 ierr = PetscMalloc1(n_is,&pcbddc->ISForDofsLocal);CHKERRQ(ierr); 813 } 814 for (i=0;i<n_is;i++) { 815 ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr); 816 pcbddc->ISForDofsLocal[i]=ISForDofs[i]; 817 } 818 pcbddc->n_ISForDofsLocal=n_is; 819 if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE; 820 pcbddc->recompute_topography = PETSC_TRUE; 821 PetscFunctionReturn(0); 822 } 823 824 #undef __FUNCT__ 825 #define __FUNCT__ "PCBDDCSetDofsSplittingLocal" 826 /*@ 827 PCBDDCSetDofsSplittingLocal - Set index sets defining fields of the local subdomain matrix 828 829 Collective 830 831 Input Parameters: 832 + pc - the preconditioning context 833 . n_is - number of index sets defining the fields 834 - ISForDofs - array of IS describing the fields in local ordering 835 836 Level: intermediate 837 838 Notes: 839 n_is should be the same among processes. Not all nodes need to be listed: unlisted nodes will belong to the complement field. 840 841 .seealso: PCBDDC 842 @*/ 843 PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc,PetscInt n_is, IS ISForDofs[]) 844 { 845 PetscInt i; 846 PetscErrorCode ierr; 847 848 PetscFunctionBegin; 849 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 850 PetscValidLogicalCollectiveInt(pc,n_is,2); 851 for (i=0;i<n_is;i++) { 852 PetscCheckSameComm(pc,1,ISForDofs[i],3); 853 PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3); 854 } 855 ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplittingLocal_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr); 856 PetscFunctionReturn(0); 857 } 858 /* -------------------------------------------------------------------------- */ 859 860 #undef __FUNCT__ 861 #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC" 862 static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[]) 863 { 864 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 865 PetscInt i; 866 PetscErrorCode ierr; 867 868 PetscFunctionBegin; 869 /* Destroy ISes if they were already set */ 870 for (i=0;i<pcbddc->n_ISForDofs;i++) { 871 ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr); 872 } 873 ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr); 874 /* last user setting takes precendence -> destroy any other customization */ 875 for (i=0;i<pcbddc->n_ISForDofsLocal;i++) { 876 ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr); 877 } 878 ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr); 879 pcbddc->n_ISForDofsLocal = 0; 880 /* allocate space then set */ 881 if (n_is) { 882 ierr = PetscMalloc1(n_is,&pcbddc->ISForDofs);CHKERRQ(ierr); 883 } 884 for (i=0;i<n_is;i++) { 885 ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr); 886 pcbddc->ISForDofs[i]=ISForDofs[i]; 887 } 888 pcbddc->n_ISForDofs=n_is; 889 if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE; 890 pcbddc->recompute_topography = PETSC_TRUE; 891 PetscFunctionReturn(0); 892 } 893 894 #undef __FUNCT__ 895 #define __FUNCT__ "PCBDDCSetDofsSplitting" 896 /*@ 897 PCBDDCSetDofsSplitting - Set index sets defining fields of the global matrix 898 899 Collective 900 901 Input Parameters: 902 + pc - the preconditioning context 903 . n_is - number of index sets defining the fields 904 - ISForDofs - array of IS describing the fields in global ordering 905 906 Level: intermediate 907 908 Notes: 909 Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field. 910 911 .seealso: PCBDDC 912 @*/ 913 PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[]) 914 { 915 PetscInt i; 916 PetscErrorCode ierr; 917 918 PetscFunctionBegin; 919 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 920 PetscValidLogicalCollectiveInt(pc,n_is,2); 921 for (i=0;i<n_is;i++) { 922 PetscCheckSameComm(pc,1,ISForDofs[i],3); 923 PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3); 924 } 925 ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr); 926 PetscFunctionReturn(0); 927 } 928 929 /* -------------------------------------------------------------------------- */ 930 #undef __FUNCT__ 931 #define __FUNCT__ "PCPreSolve_BDDC" 932 /* -------------------------------------------------------------------------- */ 933 /* 934 PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial 935 guess if a transformation of basis approach has been selected. 936 937 Input Parameter: 938 + pc - the preconditioner contex 939 940 Application Interface Routine: PCPreSolve() 941 942 Notes: 943 The interface routine PCPreSolve() is not usually called directly by 944 the user, but instead is called by KSPSolve(). 945 */ 946 static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x) 947 { 948 PetscErrorCode ierr; 949 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 950 PC_IS *pcis = (PC_IS*)(pc->data); 951 Vec used_vec; 952 PetscBool copy_rhs = PETSC_TRUE; 953 PetscBool benign_correction_is_zero = PETSC_FALSE; 954 PetscBool iscg; 955 956 PetscFunctionBegin; 957 /* if we are working with cg, one dirichlet solve can be avoided during Krylov iterations */ 958 if (ksp) { 959 ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPCG,&iscg);CHKERRQ(ierr); 960 if (!iscg) { 961 ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr); 962 } 963 } 964 /* Creates parallel work vectors used in presolve */ 965 if (!pcbddc->original_rhs) { 966 ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr); 967 } 968 if (!pcbddc->temp_solution) { 969 ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr); 970 } 971 972 if (x) { 973 ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr); 974 used_vec = x; 975 } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */ 976 ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr); 977 used_vec = pcbddc->temp_solution; 978 ierr = VecSet(used_vec,0.0);CHKERRQ(ierr); 979 } 980 981 /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */ 982 if (ksp) { 983 /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */ 984 ierr = KSPGetInitialGuessNonzero(ksp,&pcbddc->ksp_guess_nonzero);CHKERRQ(ierr); 985 if (!pcbddc->ksp_guess_nonzero) { 986 ierr = VecSet(used_vec,0.0);CHKERRQ(ierr); 987 } 988 } 989 990 pcbddc->rhs_change = PETSC_FALSE; 991 /* Take into account zeroed rows -> change rhs and store solution removed */ 992 if (rhs) { 993 IS dirIS = NULL; 994 995 /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */ 996 ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr); 997 if (dirIS) { 998 Mat_IS *matis = (Mat_IS*)pc->pmat->data; 999 PetscInt dirsize,i,*is_indices; 1000 PetscScalar *array_x; 1001 const PetscScalar *array_diagonal; 1002 1003 ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr); 1004 ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr); 1005 ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1006 ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1007 ierr = VecScatterBegin(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1008 ierr = VecScatterEnd(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1009 ierr = ISGetLocalSize(dirIS,&dirsize);CHKERRQ(ierr); 1010 ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr); 1011 ierr = VecGetArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr); 1012 ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr); 1013 for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]]; 1014 ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr); 1015 ierr = VecRestoreArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr); 1016 ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr); 1017 ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1018 ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1019 pcbddc->rhs_change = PETSC_TRUE; 1020 ierr = ISDestroy(&dirIS);CHKERRQ(ierr); 1021 } 1022 } 1023 1024 /* remove the computed solution or the initial guess from the rhs */ 1025 if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero) ) { 1026 /* store the original rhs */ 1027 if (copy_rhs) { 1028 ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr); 1029 copy_rhs = PETSC_FALSE; 1030 } 1031 pcbddc->rhs_change = PETSC_TRUE; 1032 ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr); 1033 ierr = MatMultAdd(pc->mat,used_vec,rhs,rhs);CHKERRQ(ierr); 1034 ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr); 1035 ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr); 1036 if (ksp) { 1037 ierr = KSPSetInitialGuessNonzero(ksp,PETSC_FALSE);CHKERRQ(ierr); 1038 } 1039 } 1040 ierr = VecDestroy(&used_vec);CHKERRQ(ierr); 1041 1042 /* When using the benign trick: (TODO: what about FETI-DP?) 1043 - change rhs on pressures (iteration matrix is surely of type MATIS) 1044 - compute initial vector in benign space 1045 */ 1046 if (rhs && pcbddc->benign_saddle_point) { 1047 Mat_IS *matis = (Mat_IS*)(pc->mat->data); 1048 1049 /* store the original rhs */ 1050 if (copy_rhs) { 1051 ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr); 1052 copy_rhs = PETSC_FALSE; 1053 } 1054 1055 /* now change (locally) the basis */ 1056 ierr = VecScatterBegin(matis->rctx,rhs,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1057 ierr = VecScatterEnd(matis->rctx,rhs,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1058 if (pcbddc->benign_change) { 1059 ierr = MatMultTranspose(pcbddc->benign_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 1060 ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1061 ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1062 /* change local iteration matrix */ 1063 ierr = MatPtAP(matis->A,pcbddc->benign_change,MAT_REUSE_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr); 1064 ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr); 1065 ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr); 1066 pcbddc->benign_original_mat = matis->A; 1067 ierr = MatDestroy(&matis->A);CHKERRQ(ierr); 1068 ierr = PetscObjectReference((PetscObject)pcbddc->local_mat);CHKERRQ(ierr); 1069 matis->A = pcbddc->local_mat; 1070 ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr); 1071 } else { 1072 ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1073 ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1074 } 1075 pcbddc->rhs_change = PETSC_TRUE; 1076 1077 /* compute u^*_h as in Xuemin Tu's thesis (see Section 4.8.1) */ 1078 /* TODO: what about Stokes? */ 1079 if (!pcbddc->benign_vec) { 1080 ierr = VecDuplicate(rhs,&pcbddc->benign_vec);CHKERRQ(ierr); 1081 } 1082 pcbddc->benign_p0 = 0.; 1083 if (pcbddc->benign_p0_lidx >= 0) { 1084 const PetscScalar *array; 1085 1086 ierr = VecGetArrayRead(pcis->vec2_N,&array);CHKERRQ(ierr); 1087 pcbddc->benign_p0 = array[pcbddc->benign_p0_lidx]; 1088 ierr = VecRestoreArrayRead(pcis->vec2_N,&array);CHKERRQ(ierr); 1089 } 1090 if (pcbddc->benign_null && iscg) { /* this is a workaround, need to understand more */ 1091 PetscBool iszero_l; 1092 1093 iszero_l = PetscAbsScalar(pcbddc->benign_p0) < PETSC_SMALL ? PETSC_TRUE : PETSC_FALSE; 1094 ierr = MPI_Allreduce(&iszero_l,&benign_correction_is_zero,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr); 1095 } 1096 if (!benign_correction_is_zero) { 1097 ierr = VecSet(pcis->vec1_global,0.);CHKERRQ(ierr); 1098 ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr); 1099 ierr = PCApply_BDDC(pc,pcis->vec1_global,pcbddc->benign_vec);CHKERRQ(ierr); 1100 pcbddc->benign_p0 = 0.; 1101 ierr = PCBDDCBenignGetOrSetP0(pc,pcbddc->benign_vec,PETSC_FALSE);CHKERRQ(ierr); 1102 } 1103 } 1104 1105 /* change rhs and iteration matrix if using the change of basis */ 1106 if (pcbddc->ChangeOfBasisMatrix) { 1107 PCBDDCChange_ctx change_ctx; 1108 1109 /* get change ctx */ 1110 ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr); 1111 1112 /* set current iteration matrix inside change context (change of basis has been already set into the ctx during PCSetUp) */ 1113 ierr = MatDestroy(&change_ctx->original_mat);CHKERRQ(ierr); 1114 ierr = PetscObjectReference((PetscObject)pc->mat);CHKERRQ(ierr); 1115 change_ctx->original_mat = pc->mat; 1116 1117 /* change iteration matrix */ 1118 ierr = MatDestroy(&pc->mat);CHKERRQ(ierr); 1119 ierr = PetscObjectReference((PetscObject)pcbddc->new_global_mat);CHKERRQ(ierr); 1120 pc->mat = pcbddc->new_global_mat; 1121 1122 /* store the original rhs */ 1123 if (copy_rhs) { 1124 ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr); 1125 copy_rhs = PETSC_FALSE; 1126 } 1127 1128 /* change rhs */ 1129 ierr = MatMultTranspose(change_ctx->global_change,rhs,pcis->vec1_global);CHKERRQ(ierr); 1130 ierr = VecCopy(pcis->vec1_global,rhs);CHKERRQ(ierr); 1131 pcbddc->rhs_change = PETSC_TRUE; 1132 } 1133 1134 /* remove non-benign solution from the rhs */ 1135 if (pcbddc->benign_saddle_point) { 1136 /* store the original rhs */ 1137 if (copy_rhs) { 1138 ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr); 1139 copy_rhs = PETSC_FALSE; 1140 } 1141 if (benign_correction_is_zero) { /* still need to understand why it works great */ 1142 ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr); 1143 ierr = PCApply_BDDC(pc,rhs,pcbddc->benign_vec);CHKERRQ(ierr); 1144 } 1145 ierr = VecScale(pcbddc->benign_vec,-1.0);CHKERRQ(ierr); 1146 ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,rhs,rhs);CHKERRQ(ierr); 1147 pcbddc->rhs_change = PETSC_TRUE; 1148 } 1149 1150 /* set initial guess if using PCG */ 1151 if (x && pcbddc->use_exact_dirichlet_trick) { 1152 ierr = VecSet(x,0.0);CHKERRQ(ierr); 1153 ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1154 ierr = VecScatterEnd(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1155 ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr); 1156 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1157 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1158 if (ksp) { 1159 ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr); 1160 } 1161 } 1162 if (pcbddc->benign_null) { 1163 MatNullSpace null_space; 1164 Vec nullv; 1165 PetscBool isnull; 1166 1167 pcbddc->benign_p0 = 1.; 1168 ierr = VecDuplicate(pcis->vec1_global,&nullv);CHKERRQ(ierr); 1169 ierr = VecSet(nullv,0.);CHKERRQ(ierr); 1170 ierr = PCBDDCBenignGetOrSetP0(pc,nullv,PETSC_FALSE);CHKERRQ(ierr); 1171 ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr); 1172 ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)pc),PETSC_FALSE,1,&nullv,&null_space);CHKERRQ(ierr); 1173 ierr = MatNullSpaceTest(null_space,pc->mat,&isnull);CHKERRQ(ierr); 1174 ierr = MatSetNullSpace(pc->mat,null_space);CHKERRQ(ierr); 1175 ierr = MatNullSpaceDestroy(&null_space);CHKERRQ(ierr); 1176 ierr = VecDestroy(&nullv);CHKERRQ(ierr); 1177 } 1178 1179 1180 /* remove nullspace if present */ 1181 if (ksp && x && pcbddc->NullSpace) { 1182 ierr = MatNullSpaceRemove(pcbddc->NullSpace,x);CHKERRQ(ierr); 1183 /* store the original rhs */ 1184 if (copy_rhs) { 1185 ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr); 1186 copy_rhs = PETSC_FALSE; 1187 } 1188 pcbddc->rhs_change = PETSC_TRUE; 1189 ierr = MatNullSpaceRemove(pcbddc->NullSpace,rhs);CHKERRQ(ierr); 1190 } 1191 PetscFunctionReturn(0); 1192 } 1193 1194 /* -------------------------------------------------------------------------- */ 1195 #undef __FUNCT__ 1196 #define __FUNCT__ "PCPostSolve_BDDC" 1197 /* -------------------------------------------------------------------------- */ 1198 /* 1199 PCPostSolve_BDDC - Changes the computed solution if a transformation of basis 1200 approach has been selected. Also, restores rhs to its original state. 1201 1202 Input Parameter: 1203 + pc - the preconditioner contex 1204 1205 Application Interface Routine: PCPostSolve() 1206 1207 Notes: 1208 The interface routine PCPostSolve() is not usually called directly by 1209 the user, but instead is called by KSPSolve(). 1210 */ 1211 static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x) 1212 { 1213 PetscErrorCode ierr; 1214 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 1215 1216 PetscFunctionBegin; 1217 if (pcbddc->ChangeOfBasisMatrix) { 1218 PCBDDCChange_ctx change_ctx; 1219 1220 /* get change ctx */ 1221 ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr); 1222 1223 /* restore iteration matrix */ 1224 ierr = MatDestroy(&pc->mat);CHKERRQ(ierr); 1225 ierr = PetscObjectReference((PetscObject)change_ctx->original_mat);CHKERRQ(ierr); 1226 pc->mat = change_ctx->original_mat; 1227 1228 /* need to restore the local matrices */ 1229 if (pcbddc->benign_saddle_point && pcbddc->benign_change) { 1230 Mat_IS *matis = (Mat_IS*)pc->mat->data; 1231 1232 ierr = MatDestroy(&matis->A);CHKERRQ(ierr); 1233 ierr = PetscObjectReference((PetscObject)pcbddc->benign_original_mat);CHKERRQ(ierr); 1234 matis->A = pcbddc->benign_original_mat; 1235 ierr = MatDestroy(&pcbddc->benign_original_mat);CHKERRQ(ierr); 1236 } 1237 1238 /* get solution in original basis */ 1239 if (x) { 1240 PC_IS *pcis = (PC_IS*)(pc->data); 1241 1242 /* restore solution on pressures */ 1243 if (pcbddc->benign_saddle_point) { 1244 Mat_IS *matis = (Mat_IS*)pc->mat->data; 1245 1246 /* add non-benign solution */ 1247 ierr = VecAXPY(x,-1.0,pcbddc->benign_vec);CHKERRQ(ierr); 1248 1249 /* change basis on pressures for x */ 1250 ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1251 ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1252 if (pcbddc->benign_change) { 1253 1254 ierr = MatMult(pcbddc->benign_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr); 1255 ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1256 ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1257 } else { 1258 ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1259 ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1260 } 1261 } 1262 /* change basis on x */ 1263 ierr = MatMult(change_ctx->global_change,x,pcis->vec1_global);CHKERRQ(ierr); 1264 ierr = VecCopy(pcis->vec1_global,x);CHKERRQ(ierr); 1265 } 1266 } 1267 1268 /* add solution removed in presolve */ 1269 if (x && pcbddc->rhs_change) { 1270 ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr); 1271 } 1272 1273 /* restore rhs to its original state */ 1274 if (rhs && pcbddc->rhs_change) { 1275 ierr = VecCopy(pcbddc->original_rhs,rhs);CHKERRQ(ierr); 1276 } 1277 pcbddc->rhs_change = PETSC_FALSE; 1278 1279 /* restore ksp guess state */ 1280 if (ksp) { 1281 ierr = KSPSetInitialGuessNonzero(ksp,pcbddc->ksp_guess_nonzero);CHKERRQ(ierr); 1282 } 1283 PetscFunctionReturn(0); 1284 } 1285 /* -------------------------------------------------------------------------- */ 1286 #undef __FUNCT__ 1287 #define __FUNCT__ "PCSetUp_BDDC" 1288 /* -------------------------------------------------------------------------- */ 1289 /* 1290 PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner 1291 by setting data structures and options. 1292 1293 Input Parameter: 1294 + pc - the preconditioner context 1295 1296 Application Interface Routine: PCSetUp() 1297 1298 Notes: 1299 The interface routine PCSetUp() is not usually called directly by 1300 the user, but instead is called by PCApply() if necessary. 1301 */ 1302 PetscErrorCode PCSetUp_BDDC(PC pc) 1303 { 1304 PetscErrorCode ierr; 1305 PC_BDDC* pcbddc = (PC_BDDC*)pc->data; 1306 Mat_IS* matis; 1307 MatNullSpace nearnullspace; 1308 IS zerodiag = NULL; 1309 PetscInt nrows,ncols; 1310 PetscBool computetopography,computesolvers,computesubschurs; 1311 PetscBool computeconstraintsmatrix; 1312 PetscBool new_nearnullspace_provided,ismatis; 1313 1314 PetscFunctionBegin; 1315 ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATIS,&ismatis);CHKERRQ(ierr); 1316 if (!ismatis) { 1317 SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner requires matrix of type MATIS"); 1318 } 1319 ierr = MatGetSize(pc->pmat,&nrows,&ncols);CHKERRQ(ierr); 1320 if (nrows != ncols) { 1321 SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCBDDC preconditioner requires a square preconditioning matrix"); 1322 } 1323 matis = (Mat_IS*)pc->pmat->data; 1324 /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */ 1325 /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup 1326 Also, BDDC directly build the Dirichlet problem */ 1327 /* split work */ 1328 if (pc->setupcalled) { 1329 if (pc->flag == SAME_NONZERO_PATTERN) { 1330 computetopography = PETSC_FALSE; 1331 computesolvers = PETSC_TRUE; 1332 } else { /* DIFFERENT_NONZERO_PATTERN */ 1333 computetopography = PETSC_TRUE; 1334 computesolvers = PETSC_TRUE; 1335 } 1336 } else { 1337 computetopography = PETSC_TRUE; 1338 computesolvers = PETSC_TRUE; 1339 } 1340 if (pcbddc->recompute_topography) { 1341 computetopography = PETSC_TRUE; 1342 } 1343 computeconstraintsmatrix = PETSC_FALSE; 1344 1345 /* check parameters' compatibility */ 1346 if (pcbddc->adaptive_threshold > 0.0 && !pcbddc->use_deluxe_scaling) { 1347 SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot compute adaptive constraints without deluxe scaling. Rerun with -pc_bddc_use_deluxe_scaling"); 1348 } 1349 pcbddc->adaptive_selection = (PetscBool)(pcbddc->adaptive_threshold > 0.0 && pcbddc->use_deluxe_scaling); 1350 if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE; 1351 1352 computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling); 1353 if (pcbddc->faster_deluxe && pcbddc->adaptive_selection && pcbddc->use_change_of_basis) { 1354 SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot compute faster deluxe if adaptivity and change of basis are both requested. Rerun with -pc_bddc_deluxe_faster false"); 1355 } 1356 1357 /* check if the iteration matrix is of type MATIS in case the benign trick has been requested */ 1358 ierr = PetscObjectTypeCompare((PetscObject)pc->mat,MATIS,&ismatis);CHKERRQ(ierr); 1359 if (pcbddc->benign_saddle_point && !ismatis) { 1360 SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner with benign subspace trick requires the iteration matrix to be of type MATIS"); 1361 } 1362 1363 /* Get stdout for dbg */ 1364 if (pcbddc->dbg_flag) { 1365 if (!pcbddc->dbg_viewer) { 1366 pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc)); 1367 ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr); 1368 } 1369 ierr = PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr); 1370 } 1371 1372 if (pcbddc->user_ChangeOfBasisMatrix) { 1373 /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */ 1374 pcbddc->use_change_of_basis = PETSC_FALSE; 1375 ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr); 1376 } else { 1377 ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr); 1378 ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr); 1379 pcbddc->local_mat = matis->A; 1380 } 1381 1382 /* change basis on local pressures (aka zerodiag dofs) */ 1383 if (pcbddc->benign_saddle_point) { 1384 /* detect local saddle point and change the basis in pcbddc->local_mat */ 1385 ierr = PCBDDCBenignDetectSaddlePoint(pc,&zerodiag);CHKERRQ(ierr); 1386 /* pop B0 mat from pcbddc->local_mat */ 1387 ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr); 1388 } 1389 1390 /* propagate relevant information */ 1391 /* workaround for reals */ 1392 #if !defined(PETSC_USE_COMPLEX) 1393 if (matis->A->symmetric_set) { 1394 ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr); 1395 } 1396 #endif 1397 if (matis->A->symmetric_set) { 1398 ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr); 1399 } 1400 if (matis->A->spd_set) { 1401 ierr = MatSetOption(pcbddc->local_mat,MAT_SPD,matis->A->spd);CHKERRQ(ierr); 1402 } 1403 1404 /* Set up all the "iterative substructuring" common block without computing solvers */ 1405 { 1406 Mat temp_mat; 1407 1408 temp_mat = matis->A; 1409 matis->A = pcbddc->local_mat; 1410 ierr = PCISSetUp(pc,PETSC_FALSE);CHKERRQ(ierr); 1411 pcbddc->local_mat = matis->A; 1412 matis->A = temp_mat; 1413 } 1414 1415 /* Analyze interface */ 1416 if (computetopography) { 1417 ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr); 1418 computeconstraintsmatrix = PETSC_TRUE; 1419 } 1420 1421 /* check existence of a divergence free extension, i.e. 1422 b(v_I,p_0) = 0 for all v_I (raise error if not). 1423 Also, check that PCBDDCBenignGetOrSetP0 works */ 1424 #if defined(PETSC_USE_DEBUG) 1425 if (pcbddc->benign_saddle_point) { 1426 ierr = PCBDDCBenignCheck(pc,zerodiag);CHKERRQ(ierr); 1427 } 1428 #endif 1429 1430 /* Setup local dirichlet solver ksp_D and sub_schurs solvers */ 1431 if (computesolvers) { 1432 PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs; 1433 1434 if (computesubschurs && computetopography) { 1435 ierr = PCBDDCInitSubSchurs(pc);CHKERRQ(ierr); 1436 } 1437 if (sub_schurs->use_mumps) { 1438 if (computesubschurs) { 1439 ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr); 1440 } 1441 ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr); 1442 } else { 1443 ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr); 1444 if (computesubschurs) { 1445 ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr); 1446 } 1447 } 1448 if (pcbddc->adaptive_selection) { 1449 ierr = PCBDDCAdaptiveSelection(pc);CHKERRQ(ierr); 1450 computeconstraintsmatrix = PETSC_TRUE; 1451 } 1452 } 1453 1454 /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */ 1455 new_nearnullspace_provided = PETSC_FALSE; 1456 ierr = MatGetNearNullSpace(pc->pmat,&nearnullspace);CHKERRQ(ierr); 1457 if (pcbddc->onearnullspace) { /* already used nearnullspace */ 1458 if (!nearnullspace) { /* near null space attached to mat has been destroyed */ 1459 new_nearnullspace_provided = PETSC_TRUE; 1460 } else { 1461 /* determine if the two nullspaces are different (should be lightweight) */ 1462 if (nearnullspace != pcbddc->onearnullspace) { 1463 new_nearnullspace_provided = PETSC_TRUE; 1464 } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */ 1465 PetscInt i; 1466 const Vec *nearnullvecs; 1467 PetscObjectState state; 1468 PetscInt nnsp_size; 1469 ierr = MatNullSpaceGetVecs(nearnullspace,NULL,&nnsp_size,&nearnullvecs);CHKERRQ(ierr); 1470 for (i=0;i<nnsp_size;i++) { 1471 ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&state);CHKERRQ(ierr); 1472 if (pcbddc->onearnullvecs_state[i] != state) { 1473 new_nearnullspace_provided = PETSC_TRUE; 1474 break; 1475 } 1476 } 1477 } 1478 } 1479 } else { 1480 if (!nearnullspace) { /* both nearnullspaces are null */ 1481 new_nearnullspace_provided = PETSC_FALSE; 1482 } else { /* nearnullspace attached later */ 1483 new_nearnullspace_provided = PETSC_TRUE; 1484 } 1485 } 1486 1487 /* Setup constraints and related work vectors */ 1488 /* reset primal space flags */ 1489 pcbddc->new_primal_space = PETSC_FALSE; 1490 pcbddc->new_primal_space_local = PETSC_FALSE; 1491 if (computeconstraintsmatrix || new_nearnullspace_provided) { 1492 /* It also sets the primal space flags */ 1493 ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr); 1494 /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */ 1495 ierr = PCBDDCSetUpLocalWorkVectors(pc);CHKERRQ(ierr); 1496 } 1497 1498 if (computesolvers || pcbddc->new_primal_space) { 1499 if (pcbddc->use_change_of_basis) { 1500 PC_IS *pcis = (PC_IS*)(pc->data); 1501 Mat temp_mat = NULL; 1502 1503 if (zerodiag) { 1504 /* insert B0 in pcbddc->local_mat */ 1505 ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_FALSE);CHKERRQ(ierr); 1506 /* swap local matrices */ 1507 ierr = MatISGetLocalMat(pc->pmat,&temp_mat);CHKERRQ(ierr); 1508 ierr = PetscObjectReference((PetscObject)temp_mat);CHKERRQ(ierr); 1509 ierr = MatISSetLocalMat(pc->pmat,pcbddc->local_mat);CHKERRQ(ierr); 1510 ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr); 1511 } 1512 ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr); 1513 if (zerodiag) { 1514 /* restore original matrix */ 1515 ierr = MatISSetLocalMat(pc->pmat,temp_mat);CHKERRQ(ierr); 1516 ierr = PetscObjectDereference((PetscObject)temp_mat);CHKERRQ(ierr); 1517 /* pop B0 from pcbddc->local_mat */ 1518 ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr); 1519 } 1520 /* get submatrices */ 1521 ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr); 1522 ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr); 1523 ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr); 1524 ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB);CHKERRQ(ierr); 1525 ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr); 1526 ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr); 1527 /* set flag in pcis to not reuse submatrices during PCISCreate */ 1528 pcis->reusesubmatrices = PETSC_FALSE; 1529 } else if (!pcbddc->user_ChangeOfBasisMatrix) { 1530 ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr); 1531 ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr); 1532 pcbddc->local_mat = matis->A; 1533 } 1534 /* SetUp coarse and local Neumann solvers */ 1535 ierr = PCBDDCSetUpSolvers(pc);CHKERRQ(ierr); 1536 /* SetUp Scaling operator */ 1537 ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr); 1538 } 1539 ierr = ISDestroy(&zerodiag);CHKERRQ(ierr); 1540 1541 if (pcbddc->dbg_flag) { 1542 ierr = PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr); 1543 } 1544 PetscFunctionReturn(0); 1545 } 1546 1547 /* -------------------------------------------------------------------------- */ 1548 /* 1549 PCApply_BDDC - Applies the BDDC operator to a vector. 1550 1551 Input Parameters: 1552 + pc - the preconditioner context 1553 - r - input vector (global) 1554 1555 Output Parameter: 1556 . z - output vector (global) 1557 1558 Application Interface Routine: PCApply() 1559 */ 1560 #undef __FUNCT__ 1561 #define __FUNCT__ "PCApply_BDDC" 1562 PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z) 1563 { 1564 PC_IS *pcis = (PC_IS*)(pc->data); 1565 PC_BDDC *pcbddc = (PC_BDDC*)(pc->data); 1566 PetscInt n_B = pcis->n_B, n_D = pcis->n - n_B; 1567 PetscErrorCode ierr; 1568 const PetscScalar one = 1.0; 1569 const PetscScalar m_one = -1.0; 1570 const PetscScalar zero = 0.0; 1571 1572 /* This code is similar to that provided in nn.c for PCNN 1573 NN interface preconditioner changed to BDDC 1574 Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */ 1575 1576 PetscFunctionBegin; 1577 if (pcbddc->benign_saddle_point) { /* get p0 from r */ 1578 ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr); 1579 } 1580 if (!pcbddc->use_exact_dirichlet_trick) { 1581 ierr = VecCopy(r,z);CHKERRQ(ierr); 1582 /* First Dirichlet solve */ 1583 ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1584 ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1585 /* 1586 Assembling right hand side for BDDC operator 1587 - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE) 1588 - pcis->vec1_B the interface part of the global vector z 1589 */ 1590 if (n_D) { 1591 ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr); 1592 ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr); 1593 if (pcbddc->switch_static) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); } 1594 ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr); 1595 } else { 1596 ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr); 1597 } 1598 ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1599 ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1600 ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr); 1601 } else { 1602 if (pcbddc->switch_static) { 1603 ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr); 1604 } 1605 ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr); 1606 } 1607 1608 /* Apply interface preconditioner 1609 input/output vecs: pcis->vec1_B and pcis->vec1_D */ 1610 ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr); 1611 1612 /* Apply transpose of partition of unity operator */ 1613 ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr); 1614 1615 /* Second Dirichlet solve and assembling of output */ 1616 ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1617 ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1618 if (n_B) { 1619 ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr); 1620 if (pcbddc->switch_static) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); } 1621 } else if (pcbddc->switch_static) { 1622 ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr); 1623 } 1624 ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr); 1625 1626 if (!pcbddc->use_exact_dirichlet_trick) { 1627 if (pcbddc->switch_static) { 1628 ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr); 1629 } else { 1630 ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr); 1631 } 1632 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1633 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1634 } else { 1635 if (pcbddc->switch_static) { 1636 ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr); 1637 } else { 1638 ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr); 1639 } 1640 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1641 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1642 } 1643 1644 if (pcbddc->benign_saddle_point) { /* set p0 (computed in PCBDDCApplyInterface) */ 1645 ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr); 1646 } 1647 PetscFunctionReturn(0); 1648 } 1649 1650 /* -------------------------------------------------------------------------- */ 1651 /* 1652 PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector. 1653 1654 Input Parameters: 1655 + pc - the preconditioner context 1656 - r - input vector (global) 1657 1658 Output Parameter: 1659 . z - output vector (global) 1660 1661 Application Interface Routine: PCApplyTranspose() 1662 */ 1663 #undef __FUNCT__ 1664 #define __FUNCT__ "PCApplyTranspose_BDDC" 1665 PetscErrorCode PCApplyTranspose_BDDC(PC pc,Vec r,Vec z) 1666 { 1667 PC_IS *pcis = (PC_IS*)(pc->data); 1668 PC_BDDC *pcbddc = (PC_BDDC*)(pc->data); 1669 PetscInt n_B = pcis->n_B, n_D = pcis->n - n_B; 1670 PetscErrorCode ierr; 1671 const PetscScalar one = 1.0; 1672 const PetscScalar m_one = -1.0; 1673 const PetscScalar zero = 0.0; 1674 1675 PetscFunctionBegin; 1676 if (pcbddc->benign_saddle_point) { /* get p0 from r */ 1677 ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr); 1678 } 1679 if (!pcbddc->use_exact_dirichlet_trick) { 1680 ierr = VecCopy(r,z);CHKERRQ(ierr); 1681 /* First Dirichlet solve */ 1682 ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1683 ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1684 /* 1685 Assembling right hand side for BDDC operator 1686 - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE) 1687 - pcis->vec1_B the interface part of the global vector z 1688 */ 1689 if (n_D) { 1690 ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr); 1691 ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr); 1692 if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); } 1693 ierr = MatMultTranspose(pcis->A_IB,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr); 1694 } else { 1695 ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr); 1696 } 1697 ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1698 ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1699 ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr); 1700 } else { 1701 if (pcbddc->switch_static) { 1702 ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr); 1703 } 1704 ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr); 1705 } 1706 1707 /* Apply interface preconditioner 1708 input/output vecs: pcis->vec1_B and pcis->vec1_D */ 1709 ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_TRUE);CHKERRQ(ierr); 1710 1711 /* Apply transpose of partition of unity operator */ 1712 ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr); 1713 1714 /* Second Dirichlet solve and assembling of output */ 1715 ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1716 ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1717 if (n_B) { 1718 ierr = MatMultTranspose(pcis->A_BI,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr); 1719 if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); } 1720 } else if (pcbddc->switch_static) { 1721 ierr = MatMultTranspose(pcis->A_II,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr); 1722 } 1723 ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr); 1724 if (!pcbddc->use_exact_dirichlet_trick) { 1725 if (pcbddc->switch_static) { 1726 ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr); 1727 } else { 1728 ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr); 1729 } 1730 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1731 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1732 } else { 1733 if (pcbddc->switch_static) { 1734 ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr); 1735 } else { 1736 ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr); 1737 } 1738 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1739 ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1740 } 1741 if (pcbddc->benign_saddle_point) { /* set p0 (computed in PCBDDCApplyInterface) */ 1742 ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr); 1743 } 1744 PetscFunctionReturn(0); 1745 } 1746 /* -------------------------------------------------------------------------- */ 1747 1748 #undef __FUNCT__ 1749 #define __FUNCT__ "PCDestroy_BDDC" 1750 PetscErrorCode PCDestroy_BDDC(PC pc) 1751 { 1752 PC_BDDC *pcbddc = (PC_BDDC*)pc->data; 1753 PetscErrorCode ierr; 1754 1755 PetscFunctionBegin; 1756 /* free data created by PCIS */ 1757 ierr = PCISDestroy(pc);CHKERRQ(ierr); 1758 /* free BDDC custom data */ 1759 ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr); 1760 /* destroy objects related to topography */ 1761 ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr); 1762 /* free allocated graph structure */ 1763 ierr = PetscFree(pcbddc->mat_graph);CHKERRQ(ierr); 1764 /* free allocated sub schurs structure */ 1765 ierr = PetscFree(pcbddc->sub_schurs);CHKERRQ(ierr); 1766 /* destroy objects for scaling operator */ 1767 ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr); 1768 ierr = PetscFree(pcbddc->deluxe_ctx);CHKERRQ(ierr); 1769 /* free solvers stuff */ 1770 ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr); 1771 /* free global vectors needed in presolve */ 1772 ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr); 1773 ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr); 1774 /* free stuff for change of basis hooks */ 1775 if (pcbddc->new_global_mat) { 1776 PCBDDCChange_ctx change_ctx; 1777 ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr); 1778 ierr = MatDestroy(&change_ctx->original_mat);CHKERRQ(ierr); 1779 ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr); 1780 ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr); 1781 ierr = PetscFree(change_ctx);CHKERRQ(ierr); 1782 } 1783 ierr = MatDestroy(&pcbddc->new_global_mat);CHKERRQ(ierr); 1784 /* remove functions */ 1785 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",NULL);CHKERRQ(ierr); 1786 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr); 1787 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr); 1788 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL);CHKERRQ(ierr); 1789 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL);CHKERRQ(ierr); 1790 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL);CHKERRQ(ierr); 1791 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",NULL);CHKERRQ(ierr); 1792 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr); 1793 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr); 1794 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr); 1795 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr); 1796 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr); 1797 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr); 1798 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr); 1799 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr); 1800 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr); 1801 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",NULL);CHKERRQ(ierr); 1802 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr); 1803 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr); 1804 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr); 1805 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr); 1806 /* Free the private data structure */ 1807 ierr = PetscFree(pc->data);CHKERRQ(ierr); 1808 PetscFunctionReturn(0); 1809 } 1810 /* -------------------------------------------------------------------------- */ 1811 1812 #undef __FUNCT__ 1813 #define __FUNCT__ "PCBDDCMatFETIDPGetRHS_BDDC" 1814 static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) 1815 { 1816 FETIDPMat_ctx mat_ctx; 1817 Vec copy_standard_rhs; 1818 PC_IS* pcis; 1819 PC_BDDC* pcbddc; 1820 PetscErrorCode ierr; 1821 1822 PetscFunctionBegin; 1823 ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr); 1824 pcis = (PC_IS*)mat_ctx->pc->data; 1825 pcbddc = (PC_BDDC*)mat_ctx->pc->data; 1826 1827 /* 1828 change of basis for physical rhs if needed 1829 It also changes the rhs in case of dirichlet boundaries 1830 TODO: better management when FETIDP will have its own class 1831 */ 1832 ierr = VecDuplicate(standard_rhs,©_standard_rhs);CHKERRQ(ierr); 1833 ierr = VecCopy(standard_rhs,copy_standard_rhs);CHKERRQ(ierr); 1834 ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,copy_standard_rhs,NULL);CHKERRQ(ierr); 1835 /* store vectors for computation of fetidp final solution */ 1836 ierr = VecScatterBegin(pcis->global_to_D,copy_standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1837 ierr = VecScatterEnd(pcis->global_to_D,copy_standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1838 /* scale rhs since it should be unassembled */ 1839 /* TODO use counter scaling? (also below) */ 1840 ierr = VecScatterBegin(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1841 ierr = VecScatterEnd(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1842 /* Apply partition of unity */ 1843 ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr); 1844 /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,copy_standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */ 1845 if (!pcbddc->switch_static) { 1846 /* compute partially subassembled Schur complement right-hand side */ 1847 ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr); 1848 ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr); 1849 ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr); 1850 ierr = VecSet(copy_standard_rhs,0.0);CHKERRQ(ierr); 1851 ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,copy_standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1852 ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,copy_standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1853 /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,copy_standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */ 1854 ierr = VecScatterBegin(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1855 ierr = VecScatterEnd(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1856 ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr); 1857 } 1858 ierr = VecDestroy(©_standard_rhs);CHKERRQ(ierr); 1859 /* BDDC rhs */ 1860 ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr); 1861 if (pcbddc->switch_static) { 1862 ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr); 1863 } 1864 /* apply BDDC */ 1865 ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr); 1866 /* Application of B_delta and assembling of rhs for fetidp fluxes */ 1867 ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr); 1868 ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr); 1869 ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1870 ierr = VecScatterEnd(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1871 PetscFunctionReturn(0); 1872 } 1873 1874 #undef __FUNCT__ 1875 #define __FUNCT__ "PCBDDCMatFETIDPGetRHS" 1876 /*@ 1877 PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side 1878 1879 Collective 1880 1881 Input Parameters: 1882 + fetidp_mat - the FETI-DP matrix object obtained by a call to PCBDDCCreateFETIDPOperators 1883 - standard_rhs - the right-hand side of the original linear system 1884 1885 Output Parameters: 1886 . fetidp_flux_rhs - the right-hand side for the FETI-DP linear system 1887 1888 Level: developer 1889 1890 Notes: 1891 1892 .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetSolution 1893 @*/ 1894 PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) 1895 { 1896 FETIDPMat_ctx mat_ctx; 1897 PetscErrorCode ierr; 1898 1899 PetscFunctionBegin; 1900 ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr); 1901 ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr); 1902 PetscFunctionReturn(0); 1903 } 1904 /* -------------------------------------------------------------------------- */ 1905 1906 #undef __FUNCT__ 1907 #define __FUNCT__ "PCBDDCMatFETIDPGetSolution_BDDC" 1908 static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) 1909 { 1910 FETIDPMat_ctx mat_ctx; 1911 PC_IS* pcis; 1912 PC_BDDC* pcbddc; 1913 PetscErrorCode ierr; 1914 1915 PetscFunctionBegin; 1916 ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr); 1917 pcis = (PC_IS*)mat_ctx->pc->data; 1918 pcbddc = (PC_BDDC*)mat_ctx->pc->data; 1919 1920 /* apply B_delta^T */ 1921 ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1922 ierr = VecScatterEnd (mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1923 ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr); 1924 /* compute rhs for BDDC application */ 1925 ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr); 1926 if (pcbddc->switch_static) { 1927 ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr); 1928 } 1929 /* apply BDDC */ 1930 ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr); 1931 /* put values into standard global vector */ 1932 ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1933 ierr = VecScatterEnd (pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1934 if (!pcbddc->switch_static) { 1935 /* compute values into the interior if solved for the partially subassembled Schur complement */ 1936 ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr); 1937 ierr = VecAXPY(mat_ctx->temp_solution_D,-1.0,pcis->vec1_D);CHKERRQ(ierr); 1938 ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr); 1939 } 1940 ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1941 ierr = VecScatterEnd (pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1942 /* final change of basis if needed 1943 Is also sums the dirichlet part removed during RHS assembling */ 1944 ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr); 1945 PetscFunctionReturn(0); 1946 } 1947 1948 #undef __FUNCT__ 1949 #define __FUNCT__ "PCBDDCMatFETIDPGetSolution" 1950 /*@ 1951 PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system 1952 1953 Collective 1954 1955 Input Parameters: 1956 + fetidp_mat - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators 1957 - fetidp_flux_sol - the solution of the FETI-DP linear system 1958 1959 Output Parameters: 1960 . standard_sol - the solution defined on the physical domain 1961 1962 Level: developer 1963 1964 Notes: 1965 1966 .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetRHS 1967 @*/ 1968 PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) 1969 { 1970 FETIDPMat_ctx mat_ctx; 1971 PetscErrorCode ierr; 1972 1973 PetscFunctionBegin; 1974 ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr); 1975 ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr); 1976 PetscFunctionReturn(0); 1977 } 1978 /* -------------------------------------------------------------------------- */ 1979 1980 extern PetscErrorCode FETIDPMatMult(Mat,Vec,Vec); 1981 extern PetscErrorCode FETIDPMatMultTranspose(Mat,Vec,Vec); 1982 extern PetscErrorCode PCBDDCDestroyFETIDPMat(Mat); 1983 extern PetscErrorCode FETIDPPCApply(PC,Vec,Vec); 1984 extern PetscErrorCode FETIDPPCApplyTranspose(PC,Vec,Vec); 1985 extern PetscErrorCode PCBDDCDestroyFETIDPPC(PC); 1986 1987 #undef __FUNCT__ 1988 #define __FUNCT__ "PCBDDCCreateFETIDPOperators_BDDC" 1989 static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, Mat *fetidp_mat, PC *fetidp_pc) 1990 { 1991 1992 FETIDPMat_ctx fetidpmat_ctx; 1993 Mat newmat; 1994 FETIDPPC_ctx fetidppc_ctx; 1995 PC newpc; 1996 MPI_Comm comm; 1997 PetscErrorCode ierr; 1998 1999 PetscFunctionBegin; 2000 ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr); 2001 /* FETIDP linear matrix */ 2002 ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr); 2003 ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr); 2004 ierr = MatCreateShell(comm,PETSC_DECIDE,PETSC_DECIDE,fetidpmat_ctx->n_lambda,fetidpmat_ctx->n_lambda,fetidpmat_ctx,&newmat);CHKERRQ(ierr); 2005 ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr); 2006 ierr = MatShellSetOperation(newmat,MATOP_MULT_TRANSPOSE,(void (*)(void))FETIDPMatMultTranspose);CHKERRQ(ierr); 2007 ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr); 2008 ierr = MatSetUp(newmat);CHKERRQ(ierr); 2009 /* FETIDP preconditioner */ 2010 ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr); 2011 ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr); 2012 ierr = PCCreate(comm,&newpc);CHKERRQ(ierr); 2013 ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr); 2014 ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr); 2015 ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr); 2016 ierr = PCShellSetApplyTranspose(newpc,FETIDPPCApplyTranspose);CHKERRQ(ierr); 2017 ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr); 2018 ierr = PCSetOperators(newpc,newmat,newmat);CHKERRQ(ierr); 2019 ierr = PCSetUp(newpc);CHKERRQ(ierr); 2020 /* return pointers for objects created */ 2021 *fetidp_mat=newmat; 2022 *fetidp_pc=newpc; 2023 PetscFunctionReturn(0); 2024 } 2025 2026 #undef __FUNCT__ 2027 #define __FUNCT__ "PCBDDCCreateFETIDPOperators" 2028 /*@ 2029 PCBDDCCreateFETIDPOperators - Create FETI-DP operators 2030 2031 Collective 2032 2033 Input Parameters: 2034 . pc - the BDDC preconditioning context (setup should have been called before) 2035 2036 Output Parameters: 2037 + fetidp_mat - shell FETI-DP matrix object 2038 - fetidp_pc - shell Dirichlet preconditioner for FETI-DP matrix 2039 2040 Options Database Keys: 2041 . -fetidp_fullyredundant <false> - use or not a fully redundant set of Lagrange multipliers 2042 2043 Level: developer 2044 2045 Notes: 2046 Currently the only operations provided for FETI-DP matrix are MatMult and MatMultTranspose 2047 2048 .seealso: PCBDDC, PCBDDCMatFETIDPGetRHS, PCBDDCMatFETIDPGetSolution 2049 @*/ 2050 PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, Mat *fetidp_mat, PC *fetidp_pc) 2051 { 2052 PetscErrorCode ierr; 2053 2054 PetscFunctionBegin; 2055 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 2056 if (pc->setupcalled) { 2057 ierr = PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,Mat*,PC*),(pc,fetidp_mat,fetidp_pc));CHKERRQ(ierr); 2058 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"You must call PCSetup_BDDC() first \n"); 2059 PetscFunctionReturn(0); 2060 } 2061 /* -------------------------------------------------------------------------- */ 2062 /*MC 2063 PCBDDC - Balancing Domain Decomposition by Constraints. 2064 2065 An implementation of the BDDC preconditioner based on 2066 2067 .vb 2068 [1] C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007 2069 [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 2070 [3] J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", http://arxiv.org/abs/0712.3977 2071 [4] C. Pechstein and C. R. Dohrmann. "Modern domain decomposition methods BDDC, deluxe scaling, and an algebraic approach", Seminar talk, Linz, December 2013, http://people.ricam.oeaw.ac.at/c.pechstein/pechstein-bddc2013.pdf 2072 .ve 2073 2074 The matrix to be preconditioned (Pmat) must be of type MATIS. 2075 2076 Currently works with MATIS matrices with local matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers. 2077 2078 It also works with unsymmetric and indefinite problems. 2079 2080 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. 2081 2082 Approximate local solvers are automatically adapted for singular linear problems (see [1]) if the user has provided the nullspace using PCBDDCSetNullSpace() 2083 2084 Boundary nodes are split in vertices, edges and faces classes 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() 2085 Additional information on dofs can be provided by using PCBDDCSetDofsSplitting(), PCBDDCSetDirichletBoundaries(), PCBDDCSetNeumannBoundaries(), and PCBDDCSetPrimalVerticesLocalIS() 2086 2087 Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). Non-singular modes are retained via SVD. 2088 2089 Change of basis is performed similarly to [2] when requested. When more than 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. 2090 User defined change of basis can be passed to PCBDDC by using PCBDDCSetChangeOfBasisMat() 2091 2092 The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using a MatPartitioning object. 2093 2094 Adaptive selection of primal constraints [4] is supported for SPD systems with high-contrast in the coefficients if MUMPS is present. Future versions of the code will also consider using MKL_PARDISO or PASTIX. 2095 2096 An experimental interface to the FETI-DP method is available. FETI-DP operators could be created using PCBDDCCreateFETIDPOperators(). A stand-alone class for the FETI-DP method will be provided in the next releases. 2097 Deluxe scaling is not supported yet for FETI-DP. 2098 2099 Options Database Keys (some of them, run with -h for a complete list): 2100 2101 . -pc_bddc_use_vertices <true> - use or not vertices in primal space 2102 . -pc_bddc_use_edges <true> - use or not edges in primal space 2103 . -pc_bddc_use_faces <false> - use or not faces in primal space 2104 . -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems 2105 . -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only) 2106 . -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested 2107 . -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1]) 2108 . -pc_bddc_levels <0> - maximum number of levels for multilevel 2109 . -pc_bddc_coarsening_ratio <8> - number of subdomains which will be aggregated together at the coarser level (e.g. H/h ratio at the coarser level, significative only in the multilevel case) 2110 . -pc_bddc_redistribute <0> - size of a subset of processors where the coarse problem will be remapped (the value is ignored if not at the coarsest level) 2111 . -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling 2112 . -pc_bddc_schur_layers <-1> - select the economic version of deluxe scaling by specifying the number of layers (-1 corresponds to the original deluxe scaling) 2113 . -pc_bddc_adaptive_threshold <0.0> - when a value greater than one is specified, adaptive selection of constraints is performed on edges and faces (requires deluxe scaling and MUMPS installed) 2114 - -pc_bddc_check_level <0> - set verbosity level of debugging output 2115 2116 Options for Dirichlet, Neumann or coarse solver can be set with 2117 .vb 2118 -pc_bddc_dirichlet_ 2119 -pc_bddc_neumann_ 2120 -pc_bddc_coarse_ 2121 .ve 2122 e.g -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. PCBDDC uses by default KPSPREONLY and PCLU. 2123 2124 When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified as 2125 .vb 2126 -pc_bddc_dirichlet_lN_ 2127 -pc_bddc_neumann_lN_ 2128 -pc_bddc_coarse_lN_ 2129 .ve 2130 Note that level number ranges from the finest (0) to the coarsest (N). 2131 In order to specify options for the BDDC operators at the coarser levels (and not for the solvers), prepend -pc_bddc_coarse_ or -pc_bddc_coarse_l to the option, e.g. 2132 .vb 2133 -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3 2134 .ve 2135 will use a threshold of 5 for constraints' selection at the first coarse level and will redistribute the coarse problem of the first coarse level on 3 processors 2136 2137 Level: intermediate 2138 2139 Developer notes: 2140 2141 Contributed by Stefano Zampini 2142 2143 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, MATIS 2144 M*/ 2145 2146 #undef __FUNCT__ 2147 #define __FUNCT__ "PCCreate_BDDC" 2148 PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc) 2149 { 2150 PetscErrorCode ierr; 2151 PC_BDDC *pcbddc; 2152 2153 PetscFunctionBegin; 2154 /* Creates the private data structure for this preconditioner and attach it to the PC object. */ 2155 ierr = PetscNewLog(pc,&pcbddc);CHKERRQ(ierr); 2156 pc->data = (void*)pcbddc; 2157 2158 /* create PCIS data structure */ 2159 ierr = PCISCreate(pc);CHKERRQ(ierr); 2160 2161 /* BDDC customization */ 2162 pcbddc->use_local_adj = PETSC_TRUE; 2163 pcbddc->use_vertices = PETSC_TRUE; 2164 pcbddc->use_edges = PETSC_TRUE; 2165 pcbddc->use_faces = PETSC_FALSE; 2166 pcbddc->use_change_of_basis = PETSC_FALSE; 2167 pcbddc->use_change_on_faces = PETSC_FALSE; 2168 pcbddc->switch_static = PETSC_FALSE; 2169 pcbddc->use_nnsp_true = PETSC_FALSE; 2170 pcbddc->use_qr_single = PETSC_FALSE; 2171 pcbddc->symmetric_primal = PETSC_TRUE; 2172 pcbddc->benign_saddle_point = PETSC_FALSE; 2173 pcbddc->dbg_flag = 0; 2174 /* private */ 2175 pcbddc->local_primal_size = 0; 2176 pcbddc->local_primal_size_cc = 0; 2177 pcbddc->local_primal_ref_node = 0; 2178 pcbddc->local_primal_ref_mult = 0; 2179 pcbddc->n_vertices = 0; 2180 pcbddc->primal_indices_local_idxs = 0; 2181 pcbddc->recompute_topography = PETSC_FALSE; 2182 pcbddc->coarse_size = -1; 2183 pcbddc->new_primal_space = PETSC_FALSE; 2184 pcbddc->new_primal_space_local = PETSC_FALSE; 2185 pcbddc->global_primal_indices = 0; 2186 pcbddc->onearnullspace = 0; 2187 pcbddc->onearnullvecs_state = 0; 2188 pcbddc->user_primal_vertices = 0; 2189 pcbddc->NullSpace = 0; 2190 pcbddc->temp_solution = 0; 2191 pcbddc->original_rhs = 0; 2192 pcbddc->local_mat = 0; 2193 pcbddc->ChangeOfBasisMatrix = 0; 2194 pcbddc->user_ChangeOfBasisMatrix = 0; 2195 pcbddc->new_global_mat = 0; 2196 pcbddc->coarse_vec = 0; 2197 pcbddc->coarse_ksp = 0; 2198 pcbddc->coarse_phi_B = 0; 2199 pcbddc->coarse_phi_D = 0; 2200 pcbddc->coarse_psi_B = 0; 2201 pcbddc->coarse_psi_D = 0; 2202 pcbddc->vec1_P = 0; 2203 pcbddc->vec1_R = 0; 2204 pcbddc->vec2_R = 0; 2205 pcbddc->local_auxmat1 = 0; 2206 pcbddc->local_auxmat2 = 0; 2207 pcbddc->R_to_B = 0; 2208 pcbddc->R_to_D = 0; 2209 pcbddc->ksp_D = 0; 2210 pcbddc->ksp_R = 0; 2211 pcbddc->NeumannBoundaries = 0; 2212 pcbddc->NeumannBoundariesLocal = 0; 2213 pcbddc->DirichletBoundaries = 0; 2214 pcbddc->DirichletBoundariesLocal = 0; 2215 pcbddc->user_provided_isfordofs = PETSC_FALSE; 2216 pcbddc->n_ISForDofs = 0; 2217 pcbddc->n_ISForDofsLocal = 0; 2218 pcbddc->ISForDofs = 0; 2219 pcbddc->ISForDofsLocal = 0; 2220 pcbddc->ConstraintMatrix = 0; 2221 pcbddc->use_exact_dirichlet_trick = PETSC_TRUE; 2222 pcbddc->coarse_loc_to_glob = 0; 2223 pcbddc->coarsening_ratio = 8; 2224 pcbddc->coarse_adj_red = 0; 2225 pcbddc->current_level = 0; 2226 pcbddc->max_levels = 0; 2227 pcbddc->use_coarse_estimates = PETSC_FALSE; 2228 pcbddc->redistribute_coarse = 0; 2229 pcbddc->coarse_subassembling = 0; 2230 pcbddc->coarse_subassembling_init = 0; 2231 2232 /* benign subspace trick */ 2233 pcbddc->B0_ncol = 0; 2234 pcbddc->B0_cols = NULL; 2235 pcbddc->B0_vals = NULL; 2236 pcbddc->benign_change = 0; 2237 pcbddc->benign_vec = 0; 2238 pcbddc->benign_original_mat = 0; 2239 pcbddc->benign_sf = 0; 2240 pcbddc->benign_p0_lidx = -1; 2241 pcbddc->benign_p0_gidx = -1; 2242 pcbddc->benign_null = PETSC_FALSE; 2243 2244 /* create local graph structure */ 2245 ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr); 2246 2247 /* scaling */ 2248 pcbddc->work_scaling = 0; 2249 pcbddc->use_deluxe_scaling = PETSC_FALSE; 2250 pcbddc->faster_deluxe = PETSC_FALSE; 2251 2252 /* create sub schurs structure */ 2253 ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr); 2254 pcbddc->sub_schurs_rebuild = PETSC_FALSE; 2255 pcbddc->sub_schurs_layers = -1; 2256 pcbddc->sub_schurs_use_useradj = PETSC_FALSE; 2257 2258 pcbddc->computed_rowadj = PETSC_FALSE; 2259 2260 /* adaptivity */ 2261 pcbddc->adaptive_threshold = 0.0; 2262 pcbddc->adaptive_nmax = 0; 2263 pcbddc->adaptive_nmin = 0; 2264 2265 /* function pointers */ 2266 pc->ops->apply = PCApply_BDDC; 2267 pc->ops->applytranspose = PCApplyTranspose_BDDC; 2268 pc->ops->setup = PCSetUp_BDDC; 2269 pc->ops->destroy = PCDestroy_BDDC; 2270 pc->ops->setfromoptions = PCSetFromOptions_BDDC; 2271 pc->ops->view = 0; 2272 pc->ops->applyrichardson = 0; 2273 pc->ops->applysymmetricleft = 0; 2274 pc->ops->applysymmetricright = 0; 2275 pc->ops->presolve = PCPreSolve_BDDC; 2276 pc->ops->postsolve = PCPostSolve_BDDC; 2277 2278 /* composing function */ 2279 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",PCBDDCSetChangeOfBasisMat_BDDC);CHKERRQ(ierr); 2280 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr); 2281 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr); 2282 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC);CHKERRQ(ierr); 2283 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC);CHKERRQ(ierr); 2284 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC);CHKERRQ(ierr); 2285 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",PCBDDCSetNullSpace_BDDC);CHKERRQ(ierr); 2286 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr); 2287 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",PCBDDCSetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr); 2288 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr); 2289 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",PCBDDCSetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr); 2290 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr); 2291 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",PCBDDCGetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr); 2292 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr); 2293 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",PCBDDCGetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr); 2294 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr); 2295 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",PCBDDCSetDofsSplittingLocal_BDDC);CHKERRQ(ierr); 2296 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr); 2297 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr); 2298 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr); 2299 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr); 2300 PetscFunctionReturn(0); 2301 } 2302 2303