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