153cdbc3dSStefano Zampini /* TODOLIST 2eb97c9d2SStefano Zampini 3eb97c9d2SStefano Zampini Solvers 4a0d3c3abSStefano Zampini - Add support for cholesky for coarse solver (similar to local solvers) 5eb97c9d2SStefano Zampini - Propagate ksp prefixes for solvers to mat objects? 6eb97c9d2SStefano Zampini 7eb97c9d2SStefano Zampini User interface 80f202f7eSStefano Zampini - ** DM attached to pc? 9eb97c9d2SStefano Zampini 10eb97c9d2SStefano Zampini Debugging output 11b9b85e73SStefano Zampini - * Better management of verbosity levels of debugging output 12eb97c9d2SStefano Zampini 13eb97c9d2SStefano Zampini Extra 14b9b85e73SStefano Zampini - *** Is it possible to work with PCBDDCGraph on boundary indices only (less memory consumed)? 15eb97c9d2SStefano Zampini - BDDC with MG framework? 16eb97c9d2SStefano Zampini 17eb97c9d2SStefano Zampini MATIS related operations contained in BDDC code 18eb97c9d2SStefano Zampini - Provide general case for subassembling 19eb97c9d2SStefano Zampini 2053cdbc3dSStefano Zampini */ 210c7d97c5SJed Brown 225e5bbd0aSStefano Zampini #include <petsc/private/pcbddcimpl.h> /*I "petscpc.h" I*/ /* includes for fortran wrappers */ 235e5bbd0aSStefano Zampini #include <petsc/private/pcbddcprivateimpl.h> 243b03a366Sstefano_zampini #include <petscblaslapack.h> 25674ae819SStefano Zampini 2643371fb9SStefano Zampini static PetscBool PCBDDCPackageInitialized = PETSC_FALSE; 2743371fb9SStefano Zampini 28f3d41395Sstefano_zampini static PetscBool cited = PETSC_FALSE; 299371c9d4SSatish Balay static const char citation[] = "@article{ZampiniPCBDDC,\n" 30f3d41395Sstefano_zampini "author = {Stefano Zampini},\n" 31f3d41395Sstefano_zampini "title = {{PCBDDC}: A Class of Robust Dual-Primal Methods in {PETS}c},\n" 32f3d41395Sstefano_zampini "journal = {SIAM Journal on Scientific Computing},\n" 33f3d41395Sstefano_zampini "volume = {38},\n" 34f3d41395Sstefano_zampini "number = {5},\n" 35f3d41395Sstefano_zampini "pages = {S282-S306},\n" 36f3d41395Sstefano_zampini "year = {2016},\n" 37f3d41395Sstefano_zampini "doi = {10.1137/15M1025785},\n" 38f3d41395Sstefano_zampini "URL = {http://dx.doi.org/10.1137/15M1025785},\n" 39f3d41395Sstefano_zampini "eprint = {http://dx.doi.org/10.1137/15M1025785}\n" 40f3d41395Sstefano_zampini "}\n"; 41f3d41395Sstefano_zampini 4243371fb9SStefano Zampini PetscLogEvent PC_BDDC_Topology[PETSC_PCBDDC_MAXLEVELS]; 4343371fb9SStefano Zampini PetscLogEvent PC_BDDC_LocalSolvers[PETSC_PCBDDC_MAXLEVELS]; 4443371fb9SStefano Zampini PetscLogEvent PC_BDDC_LocalWork[PETSC_PCBDDC_MAXLEVELS]; 4543371fb9SStefano Zampini PetscLogEvent PC_BDDC_CorrectionSetUp[PETSC_PCBDDC_MAXLEVELS]; 468ead10e4SStefano Zampini PetscLogEvent PC_BDDC_ApproxSetUp[PETSC_PCBDDC_MAXLEVELS]; 478ead10e4SStefano Zampini PetscLogEvent PC_BDDC_ApproxApply[PETSC_PCBDDC_MAXLEVELS]; 4843371fb9SStefano Zampini PetscLogEvent PC_BDDC_CoarseSetUp[PETSC_PCBDDC_MAXLEVELS]; 4943371fb9SStefano Zampini PetscLogEvent PC_BDDC_CoarseSolver[PETSC_PCBDDC_MAXLEVELS]; 5043371fb9SStefano Zampini PetscLogEvent PC_BDDC_AdaptiveSetUp[PETSC_PCBDDC_MAXLEVELS]; 5143371fb9SStefano Zampini PetscLogEvent PC_BDDC_Scaling[PETSC_PCBDDC_MAXLEVELS]; 5243371fb9SStefano Zampini PetscLogEvent PC_BDDC_Schurs[PETSC_PCBDDC_MAXLEVELS]; 5355c176c0SStefano Zampini PetscLogEvent PC_BDDC_Solves[PETSC_PCBDDC_MAXLEVELS][3]; 5443371fb9SStefano Zampini 55bc960bbfSJed Brown const char *const PCBDDCInterfaceExtTypes[] = {"DIRICHLET", "LUMP", "PCBDDCInterfaceExtType", "PC_BDDC_INTERFACE_EXT_", NULL}; 56bc960bbfSJed Brown 570369aaf7SStefano Zampini PetscErrorCode PCApply_BDDC(PC, Vec, Vec); 580369aaf7SStefano Zampini 59d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_BDDC(PC pc, PetscOptionItems *PetscOptionsObject) 60d71ae5a4SJacob Faibussowitsch { 610c7d97c5SJed Brown PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 62e569e4e1SStefano Zampini PetscInt nt, i; 630c7d97c5SJed Brown 640c7d97c5SJed Brown PetscFunctionBegin; 65d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "BDDC options"); 668eeda7d8SStefano Zampini /* Verbose debugging */ 679566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_check_level", "Verbose output for PCBDDC (intended for debug)", "none", pcbddc->dbg_flag, &pcbddc->dbg_flag, NULL)); 68a13144ffSStefano Zampini /* Approximate solvers */ 699566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-pc_bddc_interface_ext_type", "Use DIRICHLET or LUMP to extend interface corrections to interior", "PCBDDCSetInterfaceExtType", PCBDDCInterfaceExtTypes, (PetscEnum)pcbddc->interface_extension, (PetscEnum *)&pcbddc->interface_extension, NULL)); 70bc960bbfSJed Brown if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET) { 719566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_dirichlet_approximate", "Inform PCBDDC that we are using approximate Dirichlet solvers", "none", pcbddc->NullSpace_corr[0], &pcbddc->NullSpace_corr[0], NULL)); 729566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_dirichlet_approximate_scale", "Inform PCBDDC that we need to scale the Dirichlet solve", "none", pcbddc->NullSpace_corr[1], &pcbddc->NullSpace_corr[1], NULL)); 73bc960bbfSJed Brown } else { 74bc960bbfSJed Brown /* This flag is needed/implied by lumping */ 75bc960bbfSJed Brown pcbddc->switch_static = PETSC_TRUE; 76bc960bbfSJed Brown } 779566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_neumann_approximate", "Inform PCBDDC that we are using approximate Neumann solvers", "none", pcbddc->NullSpace_corr[2], &pcbddc->NullSpace_corr[2], NULL)); 789566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_neumann_approximate_scale", "Inform PCBDDC that we need to scale the Neumann solve", "none", pcbddc->NullSpace_corr[3], &pcbddc->NullSpace_corr[3], NULL)); 796b78500eSPatrick Sanan /* Primal space customization */ 809566063dSJacob Faibussowitsch PetscCall(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)); 819566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_graph_maxcount", "Maximum number of shared subdomains for a connected component", "none", pcbddc->graphmaxcount, &pcbddc->graphmaxcount, NULL)); 829566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_corner_selection", "Activates face-based corner selection", "none", pcbddc->corner_selection, &pcbddc->corner_selection, NULL)); 839566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_vertices", "Use or not corner dofs in coarse space", "none", pcbddc->use_vertices, &pcbddc->use_vertices, NULL)); 849566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_edges", "Use or not edge constraints in coarse space", "none", pcbddc->use_edges, &pcbddc->use_edges, NULL)); 859566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_faces", "Use or not face constraints in coarse space", "none", pcbddc->use_faces, &pcbddc->use_faces, NULL)); 869566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_vertex_size", "Connected components smaller or equal to vertex size will be considered as primal vertices", "none", pcbddc->vertex_size, &pcbddc->vertex_size, NULL)); 879566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_nnsp", "Use near null space attached to the matrix to compute constraints", "none", pcbddc->use_nnsp, &pcbddc->use_nnsp, NULL)); 889566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_nnsp_true", "Use near null space attached to the matrix to compute constraints as is", "none", pcbddc->use_nnsp_true, &pcbddc->use_nnsp_true, NULL)); 899566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_qr_single", "Use QR factorization for single constraints on cc (QR is always used when multiple constraints are present)", "none", pcbddc->use_qr_single, &pcbddc->use_qr_single, NULL)); 908eeda7d8SStefano Zampini /* Change of basis */ 919566063dSJacob Faibussowitsch PetscCall(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)); 929566063dSJacob Faibussowitsch PetscCall(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)); 93ad540459SPierre Jolivet if (!pcbddc->use_change_of_basis) pcbddc->use_change_on_faces = PETSC_FALSE; 948eeda7d8SStefano Zampini /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */ 959566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_switch_static", "Switch on static condensation ops around the interface preconditioner", "none", pcbddc->switch_static, &pcbddc->switch_static, NULL)); 969566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_coarse_eqs_per_proc", "Target number of equations per process for coarse problem redistribution (significant only at the coarsest level)", "none", pcbddc->coarse_eqs_per_proc, &pcbddc->coarse_eqs_per_proc, NULL)); 97e569e4e1SStefano Zampini i = pcbddc->coarsening_ratio; 989566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_coarsening_ratio", "Set coarsening ratio used in multilevel coarsening", "PCBDDCSetCoarseningRatio", i, &i, NULL)); 999566063dSJacob Faibussowitsch PetscCall(PCBDDCSetCoarseningRatio(pc, i)); 100e569e4e1SStefano Zampini i = pcbddc->max_levels; 1019566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_levels", "Set maximum number of levels for multilevel", "PCBDDCSetLevels", i, &i, NULL)); 1029566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLevels(pc, i)); 1039566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_coarse_eqs_limit", "Set maximum number of equations on coarsest grid to aim for", "none", pcbddc->coarse_eqs_limit, &pcbddc->coarse_eqs_limit, NULL)); 1049566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_coarse_estimates", "Use estimated eigenvalues for coarse problem", "none", pcbddc->use_coarse_estimates, &pcbddc->use_coarse_estimates, NULL)); 1059566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_use_deluxe_scaling", "Use deluxe scaling for BDDC", "none", pcbddc->use_deluxe_scaling, &pcbddc->use_deluxe_scaling, NULL)); 1069566063dSJacob Faibussowitsch PetscCall(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)); 1079566063dSJacob Faibussowitsch PetscCall(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)); 1089566063dSJacob Faibussowitsch PetscCall(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)); 1099566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_schur_exact", "Whether or not to use the exact Schur complement instead of the reduced one (which excludes size 1 cc)", "none", pcbddc->sub_schurs_exact_schur, &pcbddc->sub_schurs_exact_schur, NULL)); 1109566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_deluxe_zerorows", "Zero rows and columns of deluxe operators associated with primal dofs", "none", pcbddc->deluxe_zerorows, &pcbddc->deluxe_zerorows, NULL)); 1119566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_deluxe_singlemat", "Collapse deluxe operators", "none", pcbddc->deluxe_singlemat, &pcbddc->deluxe_singlemat, NULL)); 1129566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_adaptive_userdefined", "Use user-defined constraints (should be attached via MatSetNearNullSpace to pmat) in addition to those adaptively generated", "none", pcbddc->adaptive_userdefined, &pcbddc->adaptive_userdefined, NULL)); 113bd2a564bSStefano Zampini nt = 2; 1149566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-pc_bddc_adaptive_threshold", "Thresholds to be used for adaptive selection of constraints", "none", pcbddc->adaptive_threshold, &nt, NULL)); 115bd2a564bSStefano Zampini if (nt == 1) pcbddc->adaptive_threshold[1] = pcbddc->adaptive_threshold[0]; 1169566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_adaptive_nmin", "Minimum number of constraints per connected components", "none", pcbddc->adaptive_nmin, &pcbddc->adaptive_nmin, NULL)); 1179566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_bddc_adaptive_nmax", "Maximum number of constraints per connected components", "none", pcbddc->adaptive_nmax, &pcbddc->adaptive_nmax, NULL)); 1189566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_symmetric", "Symmetric computation of primal basis functions", "none", pcbddc->symmetric_primal, &pcbddc->symmetric_primal, NULL)); 1199566063dSJacob Faibussowitsch PetscCall(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)); 1209566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_benign_trick", "Apply the benign subspace trick to saddle point problems with discontinuous pressures", "none", pcbddc->benign_saddle_point, &pcbddc->benign_saddle_point, NULL)); 1219566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_benign_change", "Compute the pressure change of basis explicitly", "none", pcbddc->benign_change_explicit, &pcbddc->benign_change_explicit, NULL)); 1229566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_benign_compute_correction", "Compute the benign correction during PreSolve", "none", pcbddc->benign_compute_correction, &pcbddc->benign_compute_correction, NULL)); 1239566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_nonetflux", "Automatic computation of no-net-flux quadrature weights", "none", pcbddc->compute_nonetflux, &pcbddc->compute_nonetflux, NULL)); 1249566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_detect_disconnected", "Detects disconnected subdomains", "none", pcbddc->detect_disconnected, &pcbddc->detect_disconnected, NULL)); 1259566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_detect_disconnected_filter", "Filters out small entries in the local matrix when detecting disconnected subdomains", "none", pcbddc->detect_disconnected_filter, &pcbddc->detect_disconnected_filter, NULL)); 1269566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_bddc_eliminate_dirichlet", "Whether or not we want to eliminate dirichlet dofs during presolve", "none", pcbddc->eliminate_dirdofs, &pcbddc->eliminate_dirdofs, NULL)); 127d0609cedSBarry Smith PetscOptionsHeadEnd(); 1280c7d97c5SJed Brown PetscFunctionReturn(0); 1290c7d97c5SJed Brown } 1306b78500eSPatrick Sanan 131d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_BDDC(PC pc, PetscViewer viewer) 132d71ae5a4SJacob Faibussowitsch { 1336b78500eSPatrick Sanan PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 134e9627c49SStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 13571783a16SStefano Zampini PetscBool isascii; 136e9627c49SStefano Zampini PetscSubcomm subcomm; 137e9627c49SStefano Zampini PetscViewer subviewer; 1386b78500eSPatrick Sanan 1396b78500eSPatrick Sanan PetscFunctionBegin; 1409566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1416b78500eSPatrick Sanan /* ASCII viewer */ 1426b78500eSPatrick Sanan if (isascii) { 1434b2aedd3SStefano Zampini PetscMPIInt color, rank, size; 144fbad9177SStefano Zampini PetscInt64 loc[7], gsum[6], gmax[6], gmin[6], totbenign; 145e9627c49SStefano Zampini PetscScalar interface_size; 146e9627c49SStefano Zampini PetscReal ratio1 = 0., ratio2 = 0.; 147e9627c49SStefano Zampini Vec counter; 1486b78500eSPatrick Sanan 14948a46eb9SPierre Jolivet if (!pc->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, " Partial information available: preconditioner has not been setup yet\n")); 15063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use verbose output: %" PetscInt_FMT "\n", pcbddc->dbg_flag)); 1519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use user-defined CSR: %d\n", !!pcbddc->mat_graph->nvtxs_csr)); 1529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use local mat graph: %d\n", pcbddc->use_local_adj && !pcbddc->mat_graph->nvtxs_csr)); 153e9627c49SStefano Zampini if (pcbddc->mat_graph->twodim) { 1549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Connectivity graph topological dimension: 2\n")); 155e9627c49SStefano Zampini } else { 1569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Connectivity graph topological dimension: 3\n")); 157e9627c49SStefano Zampini } 15848a46eb9SPierre Jolivet if (pcbddc->graphmaxcount != PETSC_MAX_INT) PetscCall(PetscViewerASCIIPrintf(viewer, " Graph max count: %" PetscInt_FMT "\n", pcbddc->graphmaxcount)); 1599566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Corner selection: %d (selected %d)\n", pcbddc->corner_selection, pcbddc->corner_selected)); 16063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use vertices: %d (vertex size %" PetscInt_FMT ")\n", pcbddc->use_vertices, pcbddc->vertex_size)); 1619566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use edges: %d\n", pcbddc->use_edges)); 1629566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use faces: %d\n", pcbddc->use_faces)); 1639566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use true near null space: %d\n", pcbddc->use_nnsp_true)); 1649566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use QR for single constraints on cc: %d\n", pcbddc->use_qr_single)); 1659566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use change of basis on local edge nodes: %d\n", pcbddc->use_change_of_basis)); 1669566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use change of basis on local face nodes: %d\n", pcbddc->use_change_on_faces)); 1679566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " User defined change of basis matrix: %d\n", !!pcbddc->user_ChangeOfBasisMatrix)); 1689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Has change of basis matrix: %d\n", !!pcbddc->ChangeOfBasisMatrix)); 1699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Eliminate dirichlet boundary dofs: %d\n", pcbddc->eliminate_dirdofs)); 1709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Switch on static condensation ops around the interface preconditioner: %d\n", pcbddc->switch_static)); 1719566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use exact dirichlet trick: %d\n", pcbddc->use_exact_dirichlet_trick)); 1729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Interface extension: %s\n", PCBDDCInterfaceExtTypes[pcbddc->interface_extension])); 17363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Multilevel max levels: %" PetscInt_FMT "\n", pcbddc->max_levels)); 17463a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Multilevel coarsening ratio: %" PetscInt_FMT "\n", pcbddc->coarsening_ratio)); 1759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use estimated eigs for coarse problem: %d\n", pcbddc->use_coarse_estimates)); 1769566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use deluxe scaling: %d\n", pcbddc->use_deluxe_scaling)); 1779566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use deluxe zerorows: %d\n", pcbddc->deluxe_zerorows)); 1789566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use deluxe singlemat: %d\n", pcbddc->deluxe_singlemat)); 1799566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Rebuild interface graph for Schur principal minors: %d\n", pcbddc->sub_schurs_rebuild)); 18063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Number of dofs' layers for the computation of principal minors: %" PetscInt_FMT "\n", pcbddc->sub_schurs_layers)); 1819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Use user CSR graph to compute successive layers: %d\n", pcbddc->sub_schurs_use_useradj)); 182bd2a564bSStefano Zampini if (pcbddc->adaptive_threshold[1] != pcbddc->adaptive_threshold[0]) { 18363a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Adaptive constraint selection thresholds (active %d, userdefined %d): %g,%g\n", pcbddc->adaptive_selection, pcbddc->adaptive_userdefined, (double)pcbddc->adaptive_threshold[0], (double)pcbddc->adaptive_threshold[1])); 184bd2a564bSStefano Zampini } else { 18563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Adaptive constraint selection threshold (active %d, userdefined %d): %g\n", pcbddc->adaptive_selection, pcbddc->adaptive_userdefined, (double)pcbddc->adaptive_threshold[0])); 186bd2a564bSStefano Zampini } 18763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Min constraints / connected component: %" PetscInt_FMT "\n", pcbddc->adaptive_nmin)); 18863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Max constraints / connected component: %" PetscInt_FMT "\n", pcbddc->adaptive_nmax)); 1899566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Invert exact Schur complement for adaptive selection: %d\n", pcbddc->sub_schurs_exact_schur)); 1909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Symmetric computation of primal basis functions: %d\n", pcbddc->symmetric_primal)); 19163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Num. Procs. to map coarse adjacency list: %" PetscInt_FMT "\n", pcbddc->coarse_adj_red)); 19263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Coarse eqs per proc (significant at the coarsest level): %" PetscInt_FMT "\n", pcbddc->coarse_eqs_per_proc)); 1939566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Detect disconnected: %d (filter %d)\n", pcbddc->detect_disconnected, pcbddc->detect_disconnected_filter)); 1949566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Benign subspace trick: %d (change explicit %d)\n", pcbddc->benign_saddle_point, pcbddc->benign_change_explicit)); 1959566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Benign subspace trick is active: %d\n", pcbddc->benign_have_null)); 1969566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Algebraic computation of no-net-flux: %d\n", pcbddc->compute_nonetflux)); 197b74ba07aSstefano_zampini if (!pc->setupcalled) PetscFunctionReturn(0); 1986b78500eSPatrick Sanan 199fbad9177SStefano Zampini /* compute interface size */ 2009566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_B, 1.0)); 2019566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(pc->pmat, &counter, NULL)); 2029566063dSJacob Faibussowitsch PetscCall(VecSet(counter, 0.0)); 2039566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, counter, INSERT_VALUES, SCATTER_REVERSE)); 2049566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, counter, INSERT_VALUES, SCATTER_REVERSE)); 2059566063dSJacob Faibussowitsch PetscCall(VecSum(counter, &interface_size)); 2069566063dSJacob Faibussowitsch PetscCall(VecDestroy(&counter)); 207fbad9177SStefano Zampini 208fbad9177SStefano Zampini /* compute some statistics on the domain decomposition */ 209e9627c49SStefano Zampini gsum[0] = 1; 210fbad9177SStefano Zampini gsum[1] = gsum[2] = gsum[3] = gsum[4] = gsum[5] = 0; 211e9627c49SStefano Zampini loc[0] = !!pcis->n; 212e9627c49SStefano Zampini loc[1] = pcis->n - pcis->n_B; 213e9627c49SStefano Zampini loc[2] = pcis->n_B; 214e9627c49SStefano Zampini loc[3] = pcbddc->local_primal_size; 215345ecf6cSStefano Zampini loc[4] = pcis->n; 216fbad9177SStefano Zampini loc[5] = pcbddc->n_local_subs > 0 ? pcbddc->n_local_subs : (pcis->n ? 1 : 0); 217fbad9177SStefano Zampini loc[6] = pcbddc->benign_n; 2189566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(loc, gsum, 6, MPIU_INT64, MPI_SUM, 0, PetscObjectComm((PetscObject)pc))); 219fbad9177SStefano Zampini if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = -1; 2209566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(loc, gmax, 6, MPIU_INT64, MPI_MAX, 0, PetscObjectComm((PetscObject)pc))); 221fbad9177SStefano Zampini if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = PETSC_MAX_INT; 2229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(loc, gmin, 6, MPIU_INT64, MPI_MIN, 0, PetscObjectComm((PetscObject)pc))); 2239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Reduce(&loc[6], &totbenign, 1, MPIU_INT64, MPI_SUM, 0, PetscObjectComm((PetscObject)pc))); 224e9627c49SStefano Zampini if (pcbddc->coarse_size) { 225e9627c49SStefano Zampini ratio1 = pc->pmat->rmap->N / (1. * pcbddc->coarse_size); 226e9627c49SStefano Zampini ratio2 = PetscRealPart(interface_size) / pcbddc->coarse_size; 227e9627c49SStefano Zampini } 22863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "********************************** STATISTICS AT LEVEL %" PetscInt_FMT " **********************************\n", pcbddc->current_level)); 22963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Global dofs sizes: all %" PetscInt_FMT " interface %" PetscInt_FMT " coarse %" PetscInt_FMT "\n", pc->pmat->rmap->N, (PetscInt)PetscRealPart(interface_size), pcbddc->coarse_size)); 23063a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Coarsening ratios: all/coarse %" PetscInt_FMT " interface/coarse %" PetscInt_FMT "\n", (PetscInt)ratio1, (PetscInt)ratio2)); 23163a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Active processes : %" PetscInt_FMT "\n", (PetscInt)gsum[0])); 23263a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Total subdomains : %" PetscInt_FMT "\n", (PetscInt)gsum[5])); 23348a46eb9SPierre Jolivet if (pcbddc->benign_have_null) PetscCall(PetscViewerASCIIPrintf(viewer, " Benign subs : %" PetscInt_FMT "\n", (PetscInt)totbenign)); 2349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Dofs type :\tMIN\tMAX\tMEAN\n")); 23563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Interior dofs :\t%" PetscInt_FMT "\t%" PetscInt_FMT "\t%" PetscInt_FMT "\n", (PetscInt)gmin[1], (PetscInt)gmax[1], (PetscInt)(gsum[1] / gsum[0]))); 23663a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Interface dofs :\t%" PetscInt_FMT "\t%" PetscInt_FMT "\t%" PetscInt_FMT "\n", (PetscInt)gmin[2], (PetscInt)gmax[2], (PetscInt)(gsum[2] / gsum[0]))); 23763a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Primal dofs :\t%" PetscInt_FMT "\t%" PetscInt_FMT "\t%" PetscInt_FMT "\n", (PetscInt)gmin[3], (PetscInt)gmax[3], (PetscInt)(gsum[3] / gsum[0]))); 23863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Local dofs :\t%" PetscInt_FMT "\t%" PetscInt_FMT "\t%" PetscInt_FMT "\n", (PetscInt)gmin[4], (PetscInt)gmax[4], (PetscInt)(gsum[4] / gsum[0]))); 23963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " Local subs :\t%" PetscInt_FMT "\t%" PetscInt_FMT "\n", (PetscInt)gmin[5], (PetscInt)gmax[5])); 2409566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 24115579a77SStefano Zampini 2429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc), &rank)); 24315579a77SStefano Zampini 24415579a77SStefano Zampini /* local solvers */ 2459566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PetscObjectComm((PetscObject)pcbddc->ksp_D), &subviewer)); 246dd400576SPatrick Sanan if (rank == 0) { 2479566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(subviewer, "--- Interior solver (rank 0)\n")); 2489566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(subviewer)); 2499566063dSJacob Faibussowitsch PetscCall(KSPView(pcbddc->ksp_D, subviewer)); 2509566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(subviewer)); 2519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(subviewer, "--- Correction solver (rank 0)\n")); 2529566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(subviewer)); 2539566063dSJacob Faibussowitsch PetscCall(KSPView(pcbddc->ksp_R, subviewer)); 2549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(subviewer)); 2559566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(subviewer)); 25615579a77SStefano Zampini } 2579566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PetscObjectComm((PetscObject)pcbddc->ksp_D), &subviewer)); 2589566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 259e9627c49SStefano Zampini 260fbad9177SStefano Zampini /* the coarse problem can be handled by a different communicator */ 261e9627c49SStefano Zampini if (pcbddc->coarse_ksp) color = 1; 262e9627c49SStefano Zampini else color = 0; 2639566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size)); 2649566063dSJacob Faibussowitsch PetscCall(PetscSubcommCreate(PetscObjectComm((PetscObject)pc), &subcomm)); 2659566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetNumber(subcomm, PetscMin(size, 2))); 2669566063dSJacob Faibussowitsch PetscCall(PetscSubcommSetTypeGeneral(subcomm, color, rank)); 2679566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PetscSubcommChild(subcomm), &subviewer)); 268e9627c49SStefano Zampini if (color == 1) { 2699566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(subviewer, "--- Coarse solver\n")); 2709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(subviewer)); 2719566063dSJacob Faibussowitsch PetscCall(KSPView(pcbddc->coarse_ksp, subviewer)); 2729566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(subviewer)); 2739566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(subviewer)); 274e9627c49SStefano Zampini } 2759566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PetscSubcommChild(subcomm), &subviewer)); 2769566063dSJacob Faibussowitsch PetscCall(PetscSubcommDestroy(&subcomm)); 2779566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 278e9627c49SStefano Zampini } 2796b78500eSPatrick Sanan PetscFunctionReturn(0); 2806b78500eSPatrick Sanan } 281a13144ffSStefano Zampini 282d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDiscreteGradient_BDDC(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming) 283d71ae5a4SJacob Faibussowitsch { 284a13144ffSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 285a13144ffSStefano Zampini 286a13144ffSStefano Zampini PetscFunctionBegin; 2879566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)G)); 2889566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->discretegradient)); 289a13144ffSStefano Zampini pcbddc->discretegradient = G; 290a13144ffSStefano Zampini pcbddc->nedorder = order > 0 ? order : -order; 291495a2a07SStefano Zampini pcbddc->nedfield = field; 2921e0482f5SStefano Zampini pcbddc->nedglobal = global; 2931e0482f5SStefano Zampini pcbddc->conforming = conforming; 294a13144ffSStefano Zampini PetscFunctionReturn(0); 295a13144ffSStefano Zampini } 296a13144ffSStefano Zampini 297a13144ffSStefano Zampini /*@ 298a13144ffSStefano Zampini PCBDDCSetDiscreteGradient - Sets the discrete gradient 299a13144ffSStefano Zampini 300f1580f4eSBarry Smith Collective on pc 301a13144ffSStefano Zampini 302a13144ffSStefano Zampini Input Parameters: 303a13144ffSStefano Zampini + pc - the preconditioning context 304f1580f4eSBarry Smith . G - the discrete gradient matrix (in `MATAIJ` format) 305a13144ffSStefano Zampini . order - the order of the Nedelec space (1 for the lowest order) 306495a2a07SStefano Zampini . field - the field id of the Nedelec dofs (not used if the fields have not been specified) 3071e0482f5SStefano Zampini . global - the type of global ordering for the rows of G 308a13144ffSStefano Zampini - conforming - whether the mesh is conforming or not 309a13144ffSStefano Zampini 310a13144ffSStefano Zampini Level: advanced 311a13144ffSStefano Zampini 312f1580f4eSBarry Smith Note: 31395452b02SPatrick Sanan The discrete gradient matrix G is used to analyze the subdomain edges, and it should not contain any zero entry. 314495a2a07SStefano Zampini For variable order spaces, the order should be set to zero. 3151e0482f5SStefano Zampini If global is true, the rows of G should be given in global ordering for the whole dofs; 3161e0482f5SStefano Zampini if false, the ordering should be global for the Nedelec field. 3171e0482f5SStefano Zampini In the latter case, it should hold gid[i] < gid[j] iff geid[i] < geid[j], with gid the global orderding for all the dofs 3181e0482f5SStefano Zampini and geid the one for the Nedelec field. 319a13144ffSStefano Zampini 320f1580f4eSBarry Smith .seealso: `PCBDDC`, `PCBDDCSetDofsSplitting()`, `PCBDDCSetDofsSplittingLocal()`, `MATAIJ`, `PCBDDCSetDivergenceMat()` 321a13144ffSStefano Zampini @*/ 322d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDiscreteGradient(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming) 323d71ae5a4SJacob Faibussowitsch { 324a13144ffSStefano Zampini PetscFunctionBegin; 325a13144ffSStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 326a13144ffSStefano Zampini PetscValidHeaderSpecific(G, MAT_CLASSID, 2); 327a13144ffSStefano Zampini PetscValidLogicalCollectiveInt(pc, order, 3); 3281e0482f5SStefano Zampini PetscValidLogicalCollectiveInt(pc, field, 4); 3291e0482f5SStefano Zampini PetscValidLogicalCollectiveBool(pc, global, 5); 3301e0482f5SStefano Zampini PetscValidLogicalCollectiveBool(pc, conforming, 6); 3311e0482f5SStefano Zampini PetscCheckSameComm(pc, 1, G, 2); 332cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetDiscreteGradient_C", (PC, Mat, PetscInt, PetscInt, PetscBool, PetscBool), (pc, G, order, field, global, conforming)); 333a13144ffSStefano Zampini PetscFunctionReturn(0); 334a13144ffSStefano Zampini } 335a13144ffSStefano Zampini 336d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDivergenceMat_BDDC(PC pc, Mat divudotp, PetscBool trans, IS vl2l) 337d71ae5a4SJacob Faibussowitsch { 338a198735bSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 3396b78500eSPatrick Sanan 340a198735bSStefano Zampini PetscFunctionBegin; 3419566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)divudotp)); 3429566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->divudotp)); 343a198735bSStefano Zampini pcbddc->divudotp = divudotp; 3448ae0ca82SStefano Zampini pcbddc->divudotp_trans = trans; 345a198735bSStefano Zampini pcbddc->compute_nonetflux = PETSC_TRUE; 346a198735bSStefano Zampini if (vl2l) { 3479566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)vl2l)); 3489566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->divudotp_vl2l)); 349a198735bSStefano Zampini pcbddc->divudotp_vl2l = vl2l; 350a198735bSStefano Zampini } 351a198735bSStefano Zampini PetscFunctionReturn(0); 352a198735bSStefano Zampini } 3533d996552SStefano Zampini 354a198735bSStefano Zampini /*@ 355a198735bSStefano Zampini PCBDDCSetDivergenceMat - Sets the linear operator representing \int_\Omega \div {\bf u} \cdot p dx 356a198735bSStefano Zampini 357f1580f4eSBarry Smith Collective on pc 358a198735bSStefano Zampini 359a198735bSStefano Zampini Input Parameters: 360a198735bSStefano Zampini + pc - the preconditioning context 361f1580f4eSBarry Smith . divudotp - the matrix (must be of type `MATIS`) 3628ae0ca82SStefano Zampini . trans - if trans if false (resp. true), then pressures are in the test (trial) space and velocities are in the trial (test) space. 363f1580f4eSBarry Smith - vl2l - optional index set describing the local (wrt the local matrix in divudotp) to local (wrt the local matrix 364f1580f4eSBarry Smith in the preconditioning matrix) map for the velocities 365a198735bSStefano Zampini 366a198735bSStefano Zampini Level: advanced 367a198735bSStefano Zampini 36895452b02SPatrick Sanan Notes: 36995452b02SPatrick Sanan This auxiliary matrix is used to compute quadrature weights representing the net-flux across subdomain boundaries 370f1580f4eSBarry Smith 37105a3bf82SStefano Zampini If vl2l is NULL, the local ordering for velocities in divudotp should match that of the preconditioning matrix 372a198735bSStefano Zampini 373f1580f4eSBarry Smith .seealso: `PCBDDC`, `PCBDDCSetDiscreteGradient()` 374a198735bSStefano Zampini @*/ 375d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDivergenceMat(PC pc, Mat divudotp, PetscBool trans, IS vl2l) 376d71ae5a4SJacob Faibussowitsch { 377a198735bSStefano Zampini PetscBool ismatis; 378a198735bSStefano Zampini 379a198735bSStefano Zampini PetscFunctionBegin; 380a198735bSStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 381a198735bSStefano Zampini PetscValidHeaderSpecific(divudotp, MAT_CLASSID, 2); 382a198735bSStefano Zampini PetscCheckSameComm(pc, 1, divudotp, 2); 3838ae0ca82SStefano Zampini PetscValidLogicalCollectiveBool(pc, trans, 3); 3841b24a7afSStefano Zampini if (vl2l) PetscValidHeaderSpecific(vl2l, IS_CLASSID, 4); 3859566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)divudotp, MATIS, &ismatis)); 38628b400f6SJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Divergence matrix needs to be of type MATIS"); 387cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetDivergenceMat_C", (PC, Mat, PetscBool, IS), (pc, divudotp, trans, vl2l)); 388a198735bSStefano Zampini PetscFunctionReturn(0); 389a198735bSStefano Zampini } 3902d505d7fSStefano Zampini 391d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change, PetscBool interior) 392d71ae5a4SJacob Faibussowitsch { 393b9b85e73SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 394b9b85e73SStefano Zampini 395b9b85e73SStefano Zampini PetscFunctionBegin; 3969566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)change)); 3979566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->user_ChangeOfBasisMatrix)); 398b9b85e73SStefano Zampini pcbddc->user_ChangeOfBasisMatrix = change; 3991dd7afcfSStefano Zampini pcbddc->change_interior = interior; 400b9b85e73SStefano Zampini PetscFunctionReturn(0); 401b9b85e73SStefano Zampini } 40232fe681dSStefano Zampini 403b9b85e73SStefano Zampini /*@ 404906d46d4SStefano Zampini PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs 405b9b85e73SStefano Zampini 406f1580f4eSBarry Smith Collective on pc 407b9b85e73SStefano Zampini 408b9b85e73SStefano Zampini Input Parameters: 409b9b85e73SStefano Zampini + pc - the preconditioning context 4101dd7afcfSStefano Zampini . change - the change of basis matrix 4111dd7afcfSStefano Zampini - interior - whether or not the change of basis modifies interior dofs 412b9b85e73SStefano Zampini 413b9b85e73SStefano Zampini Level: intermediate 414b9b85e73SStefano Zampini 415db781477SPatrick Sanan .seealso: `PCBDDC` 416b9b85e73SStefano Zampini @*/ 417d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change, PetscBool interior) 418d71ae5a4SJacob Faibussowitsch { 419b9b85e73SStefano Zampini PetscFunctionBegin; 420b9b85e73SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 421b9b85e73SStefano Zampini PetscValidHeaderSpecific(change, MAT_CLASSID, 2); 422906d46d4SStefano Zampini PetscCheckSameComm(pc, 1, change, 2); 423906d46d4SStefano Zampini if (pc->mat) { 424906d46d4SStefano Zampini PetscInt rows_c, cols_c, rows, cols; 4259566063dSJacob Faibussowitsch PetscCall(MatGetSize(pc->mat, &rows, &cols)); 4269566063dSJacob Faibussowitsch PetscCall(MatGetSize(change, &rows_c, &cols_c)); 42763a3b9bcSJacob Faibussowitsch PetscCheck(rows_c == rows, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Invalid number of rows for change of basis matrix! %" PetscInt_FMT " != %" PetscInt_FMT, rows_c, rows); 42863a3b9bcSJacob Faibussowitsch PetscCheck(cols_c == cols, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Invalid number of columns for change of basis matrix! %" PetscInt_FMT " != %" PetscInt_FMT, cols_c, cols); 4299566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(pc->mat, &rows, &cols)); 4309566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(change, &rows_c, &cols_c)); 43163a3b9bcSJacob Faibussowitsch PetscCheck(rows_c == rows, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Invalid number of local rows for change of basis matrix! %" PetscInt_FMT " != %" PetscInt_FMT, rows_c, rows); 43263a3b9bcSJacob Faibussowitsch PetscCheck(cols_c == cols, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Invalid number of local columns for change of basis matrix! %" PetscInt_FMT " != %" PetscInt_FMT, cols_c, cols); 433906d46d4SStefano Zampini } 434cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetChangeOfBasisMat_C", (PC, Mat, PetscBool), (pc, change, interior)); 435b9b85e73SStefano Zampini PetscFunctionReturn(0); 436b9b85e73SStefano Zampini } 4372d505d7fSStefano Zampini 438d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetPrimalVerticesIS_BDDC(PC pc, IS PrimalVertices) 439d71ae5a4SJacob Faibussowitsch { 44030368db7SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 44156282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 44230368db7SStefano Zampini 44330368db7SStefano Zampini PetscFunctionBegin; 4449566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)PrimalVertices)); 44548a46eb9SPierre Jolivet if (pcbddc->user_primal_vertices) PetscCall(ISEqual(PrimalVertices, pcbddc->user_primal_vertices, &isequal)); 4469566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices)); 4479566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local)); 44830368db7SStefano Zampini pcbddc->user_primal_vertices = PrimalVertices; 44956282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 45030368db7SStefano Zampini PetscFunctionReturn(0); 45130368db7SStefano Zampini } 452ab8c8b98SStefano Zampini 45330368db7SStefano Zampini /*@ 454f1580f4eSBarry Smith PCBDDCSetPrimalVerticesIS - Set additional user defined primal vertices in `PCBDDC` 45530368db7SStefano Zampini 45630368db7SStefano Zampini Collective 45730368db7SStefano Zampini 45830368db7SStefano Zampini Input Parameters: 45930368db7SStefano Zampini + pc - the preconditioning context 46030368db7SStefano Zampini - PrimalVertices - index set of primal vertices in global numbering (can be empty) 46130368db7SStefano Zampini 46230368db7SStefano Zampini Level: intermediate 46330368db7SStefano Zampini 464f1580f4eSBarry Smith Note: 46530368db7SStefano Zampini Any process can list any global node 46630368db7SStefano Zampini 467db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`, `PCBDDCGetPrimalVerticesLocalIS()` 46830368db7SStefano Zampini @*/ 469d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetPrimalVerticesIS(PC pc, IS PrimalVertices) 470d71ae5a4SJacob Faibussowitsch { 47130368db7SStefano Zampini PetscFunctionBegin; 47230368db7SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 47330368db7SStefano Zampini PetscValidHeaderSpecific(PrimalVertices, IS_CLASSID, 2); 47430368db7SStefano Zampini PetscCheckSameComm(pc, 1, PrimalVertices, 2); 475cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetPrimalVerticesIS_C", (PC, IS), (pc, PrimalVertices)); 47630368db7SStefano Zampini PetscFunctionReturn(0); 47730368db7SStefano Zampini } 4782d505d7fSStefano Zampini 479d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetPrimalVerticesIS_BDDC(PC pc, IS *is) 480d71ae5a4SJacob Faibussowitsch { 4813100ebe3SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 4823100ebe3SStefano Zampini 4833100ebe3SStefano Zampini PetscFunctionBegin; 4843100ebe3SStefano Zampini *is = pcbddc->user_primal_vertices; 4853100ebe3SStefano Zampini PetscFunctionReturn(0); 4863100ebe3SStefano Zampini } 4873100ebe3SStefano Zampini 4883100ebe3SStefano Zampini /*@ 489f1580f4eSBarry Smith PCBDDCGetPrimalVerticesIS - Get user defined primal vertices set with `PCBDDCSetPrimalVerticesIS()` 4903100ebe3SStefano Zampini 4913100ebe3SStefano Zampini Collective 4923100ebe3SStefano Zampini 493f1580f4eSBarry Smith Input Parameter: 4943100ebe3SStefano Zampini . pc - the preconditioning context 4953100ebe3SStefano Zampini 496f1580f4eSBarry Smith Output Parameter: 4973100ebe3SStefano Zampini . is - index set of primal vertices in global numbering (NULL if not set) 4983100ebe3SStefano Zampini 4993100ebe3SStefano Zampini Level: intermediate 5003100ebe3SStefano Zampini 501db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`, `PCBDDCGetPrimalVerticesLocalIS()` 5023100ebe3SStefano Zampini @*/ 503d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetPrimalVerticesIS(PC pc, IS *is) 504d71ae5a4SJacob Faibussowitsch { 5053100ebe3SStefano Zampini PetscFunctionBegin; 5063100ebe3SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 5073100ebe3SStefano Zampini PetscValidPointer(is, 2); 508cac4c232SBarry Smith PetscUseMethod(pc, "PCBDDCGetPrimalVerticesIS_C", (PC, IS *), (pc, is)); 5093100ebe3SStefano Zampini PetscFunctionReturn(0); 5103100ebe3SStefano Zampini } 5113100ebe3SStefano Zampini 512d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices) 513d71ae5a4SJacob Faibussowitsch { 514674ae819SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 51556282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 5161e6b0712SBarry Smith 517674ae819SStefano Zampini PetscFunctionBegin; 5189566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)PrimalVertices)); 51948a46eb9SPierre Jolivet if (pcbddc->user_primal_vertices_local) PetscCall(ISEqual(PrimalVertices, pcbddc->user_primal_vertices_local, &isequal)); 5209566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices)); 5219566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local)); 52230368db7SStefano Zampini pcbddc->user_primal_vertices_local = PrimalVertices; 52356282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 524674ae819SStefano Zampini PetscFunctionReturn(0); 525674ae819SStefano Zampini } 5263100ebe3SStefano Zampini 527674ae819SStefano Zampini /*@ 528f1580f4eSBarry Smith PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in `PCBDDC` 529674ae819SStefano Zampini 53017eb1463SStefano Zampini Collective 531674ae819SStefano Zampini 532674ae819SStefano Zampini Input Parameters: 533674ae819SStefano Zampini + pc - the preconditioning context 53417eb1463SStefano Zampini - PrimalVertices - index set of primal vertices in local numbering (can be empty) 535674ae819SStefano Zampini 536674ae819SStefano Zampini Level: intermediate 537674ae819SStefano Zampini 538db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesLocalIS()` 539674ae819SStefano Zampini @*/ 540d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices) 541d71ae5a4SJacob Faibussowitsch { 542674ae819SStefano Zampini PetscFunctionBegin; 543674ae819SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 544674ae819SStefano Zampini PetscValidHeaderSpecific(PrimalVertices, IS_CLASSID, 2); 54517eb1463SStefano Zampini PetscCheckSameComm(pc, 1, PrimalVertices, 2); 546cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetPrimalVerticesLocalIS_C", (PC, IS), (pc, PrimalVertices)); 547674ae819SStefano Zampini PetscFunctionReturn(0); 548674ae819SStefano Zampini } 5492d505d7fSStefano Zampini 550d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetPrimalVerticesLocalIS_BDDC(PC pc, IS *is) 551d71ae5a4SJacob Faibussowitsch { 5523100ebe3SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 5533100ebe3SStefano Zampini 5543100ebe3SStefano Zampini PetscFunctionBegin; 5553100ebe3SStefano Zampini *is = pcbddc->user_primal_vertices_local; 5563100ebe3SStefano Zampini PetscFunctionReturn(0); 5573100ebe3SStefano Zampini } 5583100ebe3SStefano Zampini 5593100ebe3SStefano Zampini /*@ 560f1580f4eSBarry Smith PCBDDCGetPrimalVerticesLocalIS - Get user defined primal vertices set with `PCBDDCSetPrimalVerticesLocalIS()` 5613100ebe3SStefano Zampini 5623100ebe3SStefano Zampini Collective 5633100ebe3SStefano Zampini 564f1580f4eSBarry Smith Input Parameter: 5653100ebe3SStefano Zampini . pc - the preconditioning context 5663100ebe3SStefano Zampini 567f1580f4eSBarry Smith Output Parameter: 5683100ebe3SStefano Zampini . is - index set of primal vertices in local numbering (NULL if not set) 5693100ebe3SStefano Zampini 5703100ebe3SStefano Zampini Level: intermediate 5713100ebe3SStefano Zampini 572db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()` 5733100ebe3SStefano Zampini @*/ 574d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetPrimalVerticesLocalIS(PC pc, IS *is) 575d71ae5a4SJacob Faibussowitsch { 5763100ebe3SStefano Zampini PetscFunctionBegin; 5773100ebe3SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 5783100ebe3SStefano Zampini PetscValidPointer(is, 2); 579cac4c232SBarry Smith PetscUseMethod(pc, "PCBDDCGetPrimalVerticesLocalIS_C", (PC, IS *), (pc, is)); 5803100ebe3SStefano Zampini PetscFunctionReturn(0); 5813100ebe3SStefano Zampini } 5823100ebe3SStefano Zampini 583d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc, PetscInt k) 584d71ae5a4SJacob Faibussowitsch { 5854fad6a16SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 5864fad6a16SStefano Zampini 5874fad6a16SStefano Zampini PetscFunctionBegin; 5884fad6a16SStefano Zampini pcbddc->coarsening_ratio = k; 5894fad6a16SStefano Zampini PetscFunctionReturn(0); 5904fad6a16SStefano Zampini } 5911e6b0712SBarry Smith 5924fad6a16SStefano Zampini /*@ 593f1580f4eSBarry Smith PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel version 5944fad6a16SStefano Zampini 595f1580f4eSBarry Smith Logically collective on pc 5964fad6a16SStefano Zampini 5974fad6a16SStefano Zampini Input Parameters: 5984fad6a16SStefano Zampini + pc - the preconditioning context 59928509bceSStefano Zampini - k - coarsening ratio (H/h at the coarser level) 6004fad6a16SStefano Zampini 601f1580f4eSBarry Smith Options Database Key: 60267b8a455SSatish Balay . -pc_bddc_coarsening_ratio <int> - Set coarsening ratio used in multilevel coarsening 6034fad6a16SStefano Zampini 6044fad6a16SStefano Zampini Level: intermediate 6054fad6a16SStefano Zampini 606f1580f4eSBarry Smith Note: 607*d5b43468SJose E. Roman Approximately k subdomains at the finer level will be aggregated into a single subdomain at the coarser level 6084fad6a16SStefano Zampini 609db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetLevels()` 6104fad6a16SStefano Zampini @*/ 611d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetCoarseningRatio(PC pc, PetscInt k) 612d71ae5a4SJacob Faibussowitsch { 6134fad6a16SStefano Zampini PetscFunctionBegin; 6144fad6a16SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 6152b510759SStefano Zampini PetscValidLogicalCollectiveInt(pc, k, 2); 616cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetCoarseningRatio_C", (PC, PetscInt), (pc, k)); 6174fad6a16SStefano Zampini PetscFunctionReturn(0); 6184fad6a16SStefano Zampini } 6192b510759SStefano Zampini 620b8ffe317SStefano Zampini /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */ 621d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc, PetscBool flg) 622d71ae5a4SJacob Faibussowitsch { 623b8ffe317SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 624b8ffe317SStefano Zampini 625b8ffe317SStefano Zampini PetscFunctionBegin; 62685c4d303SStefano Zampini pcbddc->use_exact_dirichlet_trick = flg; 627b8ffe317SStefano Zampini PetscFunctionReturn(0); 628b8ffe317SStefano Zampini } 629b8ffe317SStefano Zampini 630d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc, PetscBool flg) 631d71ae5a4SJacob Faibussowitsch { 6322b510759SStefano Zampini PetscFunctionBegin; 6332b510759SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 634b8ffe317SStefano Zampini PetscValidLogicalCollectiveBool(pc, flg, 2); 635cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetUseExactDirichlet_C", (PC, PetscBool), (pc, flg)); 6362b510759SStefano Zampini PetscFunctionReturn(0); 6372b510759SStefano Zampini } 6381e6b0712SBarry Smith 639d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc, PetscInt level) 640d71ae5a4SJacob Faibussowitsch { 6414fad6a16SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 6424fad6a16SStefano Zampini 6434fad6a16SStefano Zampini PetscFunctionBegin; 6442b510759SStefano Zampini pcbddc->current_level = level; 6454fad6a16SStefano Zampini PetscFunctionReturn(0); 6464fad6a16SStefano Zampini } 6471e6b0712SBarry Smith 648d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetLevel(PC pc, PetscInt level) 649d71ae5a4SJacob Faibussowitsch { 650b8ffe317SStefano Zampini PetscFunctionBegin; 651b8ffe317SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 652b8ffe317SStefano Zampini PetscValidLogicalCollectiveInt(pc, level, 2); 653cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetLevel_C", (PC, PetscInt), (pc, level)); 654b8ffe317SStefano Zampini PetscFunctionReturn(0); 655b8ffe317SStefano Zampini } 656b8ffe317SStefano Zampini 657d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc, PetscInt levels) 658d71ae5a4SJacob Faibussowitsch { 6592b510759SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 6602b510759SStefano Zampini 6612b510759SStefano Zampini PetscFunctionBegin; 6627827d75bSBarry Smith PetscCheck(levels < PETSC_PCBDDC_MAXLEVELS, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Maximum number of additional levels for BDDC is %d", PETSC_PCBDDC_MAXLEVELS - 1); 6632b510759SStefano Zampini pcbddc->max_levels = levels; 6642b510759SStefano Zampini PetscFunctionReturn(0); 6652b510759SStefano Zampini } 6662b510759SStefano Zampini 6674fad6a16SStefano Zampini /*@ 668f1580f4eSBarry Smith PCBDDCSetLevels - Sets the maximum number of additional levels allowed for multilevel `PCBDDC` 6694fad6a16SStefano Zampini 670f1580f4eSBarry Smith Logically collective on pc 6714fad6a16SStefano Zampini 6724fad6a16SStefano Zampini Input Parameters: 6734fad6a16SStefano Zampini + pc - the preconditioning context 67437ebbdf7SStefano Zampini - levels - the maximum number of levels 6754fad6a16SStefano Zampini 676f1580f4eSBarry Smith Options Database Key: 67767b8a455SSatish Balay . -pc_bddc_levels <int> - Set maximum number of levels for multilevel 6784fad6a16SStefano Zampini 6794fad6a16SStefano Zampini Level: intermediate 6804fad6a16SStefano Zampini 681f1580f4eSBarry Smith Note: 68237ebbdf7SStefano Zampini The default value is 0, that gives the classical two-levels BDDC 6834fad6a16SStefano Zampini 684db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetCoarseningRatio()` 6854fad6a16SStefano Zampini @*/ 686d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetLevels(PC pc, PetscInt levels) 687d71ae5a4SJacob Faibussowitsch { 6884fad6a16SStefano Zampini PetscFunctionBegin; 6894fad6a16SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 6902b510759SStefano Zampini PetscValidLogicalCollectiveInt(pc, levels, 2); 691cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetLevels_C", (PC, PetscInt), (pc, levels)); 6924fad6a16SStefano Zampini PetscFunctionReturn(0); 6934fad6a16SStefano Zampini } 6941e6b0712SBarry Smith 695d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc, IS DirichletBoundaries) 696d71ae5a4SJacob Faibussowitsch { 6973b03a366Sstefano_zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 69856282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 6993b03a366Sstefano_zampini 7003b03a366Sstefano_zampini PetscFunctionBegin; 7019566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)DirichletBoundaries)); 70248a46eb9SPierre Jolivet if (pcbddc->DirichletBoundaries) PetscCall(ISEqual(DirichletBoundaries, pcbddc->DirichletBoundaries, &isequal)); 703a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 7049566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal)); 7059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundaries)); 70636e030ebSStefano Zampini pcbddc->DirichletBoundaries = DirichletBoundaries; 70756282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 7083b03a366Sstefano_zampini PetscFunctionReturn(0); 7093b03a366Sstefano_zampini } 7101e6b0712SBarry Smith 7113b03a366Sstefano_zampini /*@ 71228509bceSStefano Zampini PCBDDCSetDirichletBoundaries - Set IS defining Dirichlet boundaries for the global problem. 7133b03a366Sstefano_zampini 714785d1243SStefano Zampini Collective 7153b03a366Sstefano_zampini 7163b03a366Sstefano_zampini Input Parameters: 7173b03a366Sstefano_zampini + pc - the preconditioning context 718785d1243SStefano Zampini - DirichletBoundaries - parallel IS defining the Dirichlet boundaries 7193b03a366Sstefano_zampini 7203b03a366Sstefano_zampini Level: intermediate 7213b03a366Sstefano_zampini 722f1580f4eSBarry Smith Note: 723f1580f4eSBarry Smith Provide the information if you used `MatZeroRows()` or `MatZeroRowsColumns()`. Any process can list any global node 7243b03a366Sstefano_zampini 725db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetDirichletBoundariesLocal()`, `MatZeroRows()`, `MatZeroRowsColumns()` 7263b03a366Sstefano_zampini @*/ 727d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc, IS DirichletBoundaries) 728d71ae5a4SJacob Faibussowitsch { 7293b03a366Sstefano_zampini PetscFunctionBegin; 7303b03a366Sstefano_zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 731674ae819SStefano Zampini PetscValidHeaderSpecific(DirichletBoundaries, IS_CLASSID, 2); 732785d1243SStefano Zampini PetscCheckSameComm(pc, 1, DirichletBoundaries, 2); 733cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetDirichletBoundaries_C", (PC, IS), (pc, DirichletBoundaries)); 7343b03a366Sstefano_zampini PetscFunctionReturn(0); 7353b03a366Sstefano_zampini } 7361e6b0712SBarry Smith 737d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc, IS DirichletBoundaries) 738d71ae5a4SJacob Faibussowitsch { 7393b03a366Sstefano_zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 74056282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 7413b03a366Sstefano_zampini 7423b03a366Sstefano_zampini PetscFunctionBegin; 7439566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)DirichletBoundaries)); 74448a46eb9SPierre Jolivet if (pcbddc->DirichletBoundariesLocal) PetscCall(ISEqual(DirichletBoundaries, pcbddc->DirichletBoundariesLocal, &isequal)); 745a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 7469566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal)); 7479566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->DirichletBoundaries)); 748785d1243SStefano Zampini pcbddc->DirichletBoundariesLocal = DirichletBoundaries; 74956282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 7503b03a366Sstefano_zampini PetscFunctionReturn(0); 7513b03a366Sstefano_zampini } 7523b03a366Sstefano_zampini 7533b03a366Sstefano_zampini /*@ 75482ba6b80SStefano Zampini PCBDDCSetDirichletBoundariesLocal - Set IS defining Dirichlet boundaries for the global problem in local ordering. 7553b03a366Sstefano_zampini 756785d1243SStefano Zampini Collective 7573b03a366Sstefano_zampini 7583b03a366Sstefano_zampini Input Parameters: 7593b03a366Sstefano_zampini + pc - the preconditioning context 76082ba6b80SStefano Zampini - DirichletBoundaries - parallel IS defining the Dirichlet boundaries (in local ordering) 7613b03a366Sstefano_zampini 7623b03a366Sstefano_zampini Level: intermediate 7633b03a366Sstefano_zampini 764db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetDirichletBoundaries()`, `MatZeroRows()`, `MatZeroRowsColumns()` 7653b03a366Sstefano_zampini @*/ 766d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc, IS DirichletBoundaries) 767d71ae5a4SJacob Faibussowitsch { 7683b03a366Sstefano_zampini PetscFunctionBegin; 7693b03a366Sstefano_zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 7703b03a366Sstefano_zampini PetscValidHeaderSpecific(DirichletBoundaries, IS_CLASSID, 2); 77182ba6b80SStefano Zampini PetscCheckSameComm(pc, 1, DirichletBoundaries, 2); 772cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetDirichletBoundariesLocal_C", (PC, IS), (pc, DirichletBoundaries)); 7733b03a366Sstefano_zampini PetscFunctionReturn(0); 7743b03a366Sstefano_zampini } 7753b03a366Sstefano_zampini 776d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc, IS NeumannBoundaries) 777d71ae5a4SJacob Faibussowitsch { 7780c7d97c5SJed Brown PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 77956282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 7800c7d97c5SJed Brown 7810c7d97c5SJed Brown PetscFunctionBegin; 7829566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries)); 78348a46eb9SPierre Jolivet if (pcbddc->NeumannBoundaries) PetscCall(ISEqual(NeumannBoundaries, pcbddc->NeumannBoundaries, &isequal)); 784a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 7859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal)); 7869566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundaries)); 78736e030ebSStefano Zampini pcbddc->NeumannBoundaries = NeumannBoundaries; 78856282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 7890c7d97c5SJed Brown PetscFunctionReturn(0); 7900c7d97c5SJed Brown } 7911e6b0712SBarry Smith 79257527edcSJed Brown /*@ 793f1580f4eSBarry Smith PCBDDCSetNeumannBoundaries - Set `IS` defining Neumann boundaries for the global problem. 79457527edcSJed Brown 795f1580f4eSBarry Smith Collective on pc 79657527edcSJed Brown 79757527edcSJed Brown Input Parameters: 79857527edcSJed Brown + pc - the preconditioning context 799785d1243SStefano Zampini - NeumannBoundaries - parallel IS defining the Neumann boundaries 80057527edcSJed Brown 80157527edcSJed Brown Level: intermediate 80257527edcSJed Brown 803f1580f4eSBarry Smith Note: 8040f202f7eSStefano Zampini Any process can list any global node 80557527edcSJed Brown 806db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetNeumannBoundariesLocal()` 80757527edcSJed Brown @*/ 808d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc, IS NeumannBoundaries) 809d71ae5a4SJacob Faibussowitsch { 8100c7d97c5SJed Brown PetscFunctionBegin; 8110c7d97c5SJed Brown PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 812674ae819SStefano Zampini PetscValidHeaderSpecific(NeumannBoundaries, IS_CLASSID, 2); 813785d1243SStefano Zampini PetscCheckSameComm(pc, 1, NeumannBoundaries, 2); 814cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetNeumannBoundaries_C", (PC, IS), (pc, NeumannBoundaries)); 81553cdbc3dSStefano Zampini PetscFunctionReturn(0); 81653cdbc3dSStefano Zampini } 8171e6b0712SBarry Smith 818d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc, IS NeumannBoundaries) 819d71ae5a4SJacob Faibussowitsch { 8200c7d97c5SJed Brown PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 82156282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 8220c7d97c5SJed Brown 8230c7d97c5SJed Brown PetscFunctionBegin; 8249566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries)); 82548a46eb9SPierre Jolivet if (pcbddc->NeumannBoundariesLocal) PetscCall(ISEqual(NeumannBoundaries, pcbddc->NeumannBoundariesLocal, &isequal)); 826a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 8279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal)); 8289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pcbddc->NeumannBoundaries)); 829785d1243SStefano Zampini pcbddc->NeumannBoundariesLocal = NeumannBoundaries; 83056282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 8310c7d97c5SJed Brown PetscFunctionReturn(0); 8320c7d97c5SJed Brown } 8330c7d97c5SJed Brown 8340c7d97c5SJed Brown /*@ 83582ba6b80SStefano Zampini PCBDDCSetNeumannBoundariesLocal - Set IS defining Neumann boundaries for the global problem in local ordering. 8360c7d97c5SJed Brown 837785d1243SStefano Zampini Collective 8380c7d97c5SJed Brown 8390c7d97c5SJed Brown Input Parameters: 8400c7d97c5SJed Brown + pc - the preconditioning context 84182ba6b80SStefano Zampini - NeumannBoundaries - parallel IS defining the subdomain part of Neumann boundaries (in local ordering) 8420c7d97c5SJed Brown 8430c7d97c5SJed Brown Level: intermediate 8440c7d97c5SJed Brown 845f1580f4eSBarry Smith .seealso: `PCBDDC`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCGetDirichletBoundaries()` 8460c7d97c5SJed Brown @*/ 847d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc, IS NeumannBoundaries) 848d71ae5a4SJacob Faibussowitsch { 8490c7d97c5SJed Brown PetscFunctionBegin; 8500c7d97c5SJed Brown PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 8510c7d97c5SJed Brown PetscValidHeaderSpecific(NeumannBoundaries, IS_CLASSID, 2); 85282ba6b80SStefano Zampini PetscCheckSameComm(pc, 1, NeumannBoundaries, 2); 853cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetNeumannBoundariesLocal_C", (PC, IS), (pc, NeumannBoundaries)); 85453cdbc3dSStefano Zampini PetscFunctionReturn(0); 85553cdbc3dSStefano Zampini } 85653cdbc3dSStefano Zampini 857d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc, IS *DirichletBoundaries) 858d71ae5a4SJacob Faibussowitsch { 859da1bb401SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 860da1bb401SStefano Zampini 861da1bb401SStefano Zampini PetscFunctionBegin; 862da1bb401SStefano Zampini *DirichletBoundaries = pcbddc->DirichletBoundaries; 863da1bb401SStefano Zampini PetscFunctionReturn(0); 864da1bb401SStefano Zampini } 8651e6b0712SBarry Smith 866da1bb401SStefano Zampini /*@ 867f1580f4eSBarry Smith PCBDDCGetDirichletBoundaries - Get parallel `IS` for Dirichlet boundaries 868da1bb401SStefano Zampini 869785d1243SStefano Zampini Collective 870785d1243SStefano Zampini 871f1580f4eSBarry Smith Input Parameter: 872785d1243SStefano Zampini . pc - the preconditioning context 873785d1243SStefano Zampini 874f1580f4eSBarry Smith Output Parameter: 875785d1243SStefano Zampini . DirichletBoundaries - index set defining the Dirichlet boundaries 876785d1243SStefano Zampini 877785d1243SStefano Zampini Level: intermediate 878785d1243SStefano Zampini 879f1580f4eSBarry Smith Note: 880f1580f4eSBarry Smith The `IS` returned (if any) is the same passed in earlier by the user with `PCBDDCSetDirichletBoundaries()` 881785d1243SStefano Zampini 882f1580f4eSBarry Smith .seealso: `PCBDDC`, `PCBDDCSetDirichletBoundaries()` 883785d1243SStefano Zampini @*/ 884d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc, IS *DirichletBoundaries) 885d71ae5a4SJacob Faibussowitsch { 886785d1243SStefano Zampini PetscFunctionBegin; 887785d1243SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 888cac4c232SBarry Smith PetscUseMethod(pc, "PCBDDCGetDirichletBoundaries_C", (PC, IS *), (pc, DirichletBoundaries)); 889785d1243SStefano Zampini PetscFunctionReturn(0); 890785d1243SStefano Zampini } 891785d1243SStefano Zampini 892d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc, IS *DirichletBoundaries) 893d71ae5a4SJacob Faibussowitsch { 894785d1243SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 895785d1243SStefano Zampini 896785d1243SStefano Zampini PetscFunctionBegin; 897785d1243SStefano Zampini *DirichletBoundaries = pcbddc->DirichletBoundariesLocal; 898785d1243SStefano Zampini PetscFunctionReturn(0); 899785d1243SStefano Zampini } 900785d1243SStefano Zampini 901da1bb401SStefano Zampini /*@ 902f1580f4eSBarry Smith PCBDDCGetDirichletBoundariesLocal - Get parallel `IS` for Dirichlet boundaries (in local ordering) 903da1bb401SStefano Zampini 904785d1243SStefano Zampini Collective 905da1bb401SStefano Zampini 906f1580f4eSBarry Smith Input Parameter: 90728509bceSStefano Zampini . pc - the preconditioning context 908da1bb401SStefano Zampini 909f1580f4eSBarry Smith Output Parameter: 91028509bceSStefano Zampini . DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries 911da1bb401SStefano Zampini 912da1bb401SStefano Zampini Level: intermediate 913da1bb401SStefano Zampini 914f1580f4eSBarry Smith Note: 915f1580f4eSBarry Smith The `IS` returned could be the same passed in earlier by the user (if provided with `PCBDDCSetDirichletBoundariesLocal()`) 916f1580f4eSBarry Smith or a global-to-local map of the global `IS` (if provided with `PCBDDCSetDirichletBoundaries()`). 917f1580f4eSBarry Smith In the latter case, the `IS` will be available only after `PCSetUp()`. 918da1bb401SStefano Zampini 919f1580f4eSBarry Smith .seealso: `PCBDDC`, `PCBDDCGetDirichletBoundariesLocal()`, `PCBDDCGetDirichletBoundaries()`, `PCBDDCSetDirichletBoundaries()` 920da1bb401SStefano Zampini @*/ 921d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc, IS *DirichletBoundaries) 922d71ae5a4SJacob Faibussowitsch { 923da1bb401SStefano Zampini PetscFunctionBegin; 924da1bb401SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 925cac4c232SBarry Smith PetscUseMethod(pc, "PCBDDCGetDirichletBoundariesLocal_C", (PC, IS *), (pc, DirichletBoundaries)); 926da1bb401SStefano Zampini PetscFunctionReturn(0); 927da1bb401SStefano Zampini } 9281e6b0712SBarry Smith 929d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc, IS *NeumannBoundaries) 930d71ae5a4SJacob Faibussowitsch { 93153cdbc3dSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 93253cdbc3dSStefano Zampini 93353cdbc3dSStefano Zampini PetscFunctionBegin; 93453cdbc3dSStefano Zampini *NeumannBoundaries = pcbddc->NeumannBoundaries; 93553cdbc3dSStefano Zampini PetscFunctionReturn(0); 93653cdbc3dSStefano Zampini } 9371e6b0712SBarry Smith 93853cdbc3dSStefano Zampini /*@ 939f1580f4eSBarry Smith PCBDDCGetNeumannBoundaries - Get parallel `IS` for Neumann boundaries 94053cdbc3dSStefano Zampini 941f1580f4eSBarry Smith Not Collective 942785d1243SStefano Zampini 943f1580f4eSBarry Smith Input Parameter: 944785d1243SStefano Zampini . pc - the preconditioning context 945785d1243SStefano Zampini 946f1580f4eSBarry Smith Output Parameter: 947785d1243SStefano Zampini . NeumannBoundaries - index set defining the Neumann boundaries 948785d1243SStefano Zampini 949785d1243SStefano Zampini Level: intermediate 950785d1243SStefano Zampini 951f1580f4eSBarry Smith Note: 952f1580f4eSBarry Smith The `IS` returned (if any) is the same passed in earlier by the user with `PCBDDCSetNeumannBoundaries()` 953785d1243SStefano Zampini 954f1580f4eSBarry Smith .seealso: `PCBDDC`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCGetDirichletBoundaries()`, `PCBDDCSetDirichletBoundaries()` 955785d1243SStefano Zampini @*/ 956d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc, IS *NeumannBoundaries) 957d71ae5a4SJacob Faibussowitsch { 958785d1243SStefano Zampini PetscFunctionBegin; 959785d1243SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 960cac4c232SBarry Smith PetscUseMethod(pc, "PCBDDCGetNeumannBoundaries_C", (PC, IS *), (pc, NeumannBoundaries)); 961785d1243SStefano Zampini PetscFunctionReturn(0); 962785d1243SStefano Zampini } 963785d1243SStefano Zampini 964d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc, IS *NeumannBoundaries) 965d71ae5a4SJacob Faibussowitsch { 966785d1243SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 967785d1243SStefano Zampini 968785d1243SStefano Zampini PetscFunctionBegin; 969785d1243SStefano Zampini *NeumannBoundaries = pcbddc->NeumannBoundariesLocal; 970785d1243SStefano Zampini PetscFunctionReturn(0); 971785d1243SStefano Zampini } 972785d1243SStefano Zampini 97353cdbc3dSStefano Zampini /*@ 974f1580f4eSBarry Smith PCBDDCGetNeumannBoundariesLocal - Get parallel `IS` for Neumann boundaries (in local ordering) 97553cdbc3dSStefano Zampini 976f1580f4eSBarry Smith Not Collective 97753cdbc3dSStefano Zampini 978f1580f4eSBarry Smith Input Parameter: 97928509bceSStefano Zampini . pc - the preconditioning context 98053cdbc3dSStefano Zampini 981f1580f4eSBarry Smith Output Parameter: 98228509bceSStefano Zampini . NeumannBoundaries - index set defining the subdomain part of Neumann boundaries 98353cdbc3dSStefano Zampini 98453cdbc3dSStefano Zampini Level: intermediate 98553cdbc3dSStefano Zampini 986f1580f4eSBarry Smith Note: 987f1580f4eSBarry Smith The `IS` returned could be the same passed in earlier by the user (if provided with `PCBDDCSetNeumannBoundariesLocal()` 988f1580f4eSBarry Smith or a global-to-local map of the global `IS` (if provided with `PCBDDCSetNeumannBoundaries()`). 989f1580f4eSBarry Smith In the latter case, the `IS` will be available after `PCSetUp()`. 99053cdbc3dSStefano Zampini 991f1580f4eSBarry Smith .seealso: `PCBDDC``PCBDDCSetNeumannBoundaries()`, `PCBDDCSetNeumannBoundariesLocal)`, `PCBDDCGetNeumannBoundaries()` 99253cdbc3dSStefano Zampini @*/ 993d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc, IS *NeumannBoundaries) 994d71ae5a4SJacob Faibussowitsch { 99553cdbc3dSStefano Zampini PetscFunctionBegin; 99653cdbc3dSStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 997cac4c232SBarry Smith PetscUseMethod(pc, "PCBDDCGetNeumannBoundariesLocal_C", (PC, IS *), (pc, NeumannBoundaries)); 9980c7d97c5SJed Brown PetscFunctionReturn(0); 9990c7d97c5SJed Brown } 10001e6b0712SBarry Smith 1001d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs, const PetscInt xadj[], const PetscInt adjncy[], PetscCopyMode copymode) 1002d71ae5a4SJacob Faibussowitsch { 100336e030ebSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 1004da1bb401SStefano Zampini PCBDDCGraph mat_graph = pcbddc->mat_graph; 100556282151SStefano Zampini PetscBool same_data = PETSC_FALSE; 100636e030ebSStefano Zampini 100736e030ebSStefano Zampini PetscFunctionBegin; 10088687889aSStefano Zampini if (!nvtxs) { 100904194a47SStefano Zampini if (copymode == PETSC_OWN_POINTER) { 10109566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 10119566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 101204194a47SStefano Zampini } 10139566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphResetCSR(mat_graph)); 10148687889aSStefano Zampini PetscFunctionReturn(0); 10158687889aSStefano Zampini } 101666da6bd7Sstefano_zampini if (mat_graph->nvtxs == nvtxs && mat_graph->freecsr) { /* we own the data */ 101756282151SStefano Zampini if (mat_graph->xadj == xadj && mat_graph->adjncy == adjncy) same_data = PETSC_TRUE; 101856282151SStefano Zampini if (!same_data && mat_graph->xadj[nvtxs] == xadj[nvtxs]) { 10199566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(xadj, mat_graph->xadj, nvtxs + 1, &same_data)); 102048a46eb9SPierre Jolivet if (same_data) PetscCall(PetscArraycmp(adjncy, mat_graph->adjncy, xadj[nvtxs], &same_data)); 102156282151SStefano Zampini } 102256282151SStefano Zampini } 102356282151SStefano Zampini if (!same_data) { 1024674ae819SStefano Zampini /* free old CSR */ 10259566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphResetCSR(mat_graph)); 1026674ae819SStefano Zampini /* get CSR into graph structure */ 1027da1bb401SStefano Zampini if (copymode == PETSC_COPY_VALUES) { 10289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nvtxs + 1, &mat_graph->xadj)); 10299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(xadj[nvtxs], &mat_graph->adjncy)); 10309566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mat_graph->xadj, xadj, nvtxs + 1)); 10319566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mat_graph->adjncy, adjncy, xadj[nvtxs])); 1032a1dbd327SStefano Zampini mat_graph->freecsr = PETSC_TRUE; 1033da1bb401SStefano Zampini } else if (copymode == PETSC_OWN_POINTER) { 10341a83f524SJed Brown mat_graph->xadj = (PetscInt *)xadj; 10351a83f524SJed Brown mat_graph->adjncy = (PetscInt *)adjncy; 1036a1dbd327SStefano Zampini mat_graph->freecsr = PETSC_TRUE; 1037a1dbd327SStefano Zampini } else if (copymode == PETSC_USE_POINTER) { 1038a1dbd327SStefano Zampini mat_graph->xadj = (PetscInt *)xadj; 1039a1dbd327SStefano Zampini mat_graph->adjncy = (PetscInt *)adjncy; 1040a1dbd327SStefano Zampini mat_graph->freecsr = PETSC_FALSE; 104163a3b9bcSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported copy mode %d", copymode); 1042575ad6abSStefano Zampini mat_graph->nvtxs_csr = nvtxs; 104356282151SStefano Zampini pcbddc->recompute_topography = PETSC_TRUE; 104456282151SStefano Zampini } 104536e030ebSStefano Zampini PetscFunctionReturn(0); 104636e030ebSStefano Zampini } 10471e6b0712SBarry Smith 104836e030ebSStefano Zampini /*@ 104954fffbccSStefano Zampini PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local degrees of freedom. 105036e030ebSStefano Zampini 105136e030ebSStefano Zampini Not collective 105236e030ebSStefano Zampini 105336e030ebSStefano Zampini Input Parameters: 105454fffbccSStefano Zampini + pc - the preconditioning context. 105554fffbccSStefano Zampini . nvtxs - number of local vertices of the graph (i.e., the number of local dofs). 105654fffbccSStefano Zampini . xadj, adjncy - the connectivity of the dofs in CSR format. 1057f1580f4eSBarry Smith - copymode - supported modes are `PETSC_COPY_VALUES`, `PETSC_USE_POINTER` or `PETSC_OWN_POINTER`. 105836e030ebSStefano Zampini 105936e030ebSStefano Zampini Level: intermediate 106036e030ebSStefano Zampini 1061f1580f4eSBarry Smith Note: 106295452b02SPatrick Sanan A dof is considered connected with all local dofs if xadj[dof+1]-xadj[dof] == 1 and adjncy[xadj[dof]] is negative. 106336e030ebSStefano Zampini 106416b07851SJed Brown .seealso: `PCBDDC`, `PetscCopyMode` 106536e030ebSStefano Zampini @*/ 1066d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc, PetscInt nvtxs, const PetscInt xadj[], const PetscInt adjncy[], PetscCopyMode copymode) 1067d71ae5a4SJacob Faibussowitsch { 10680a545947SLisandro Dalcin void (*f)(void) = NULL; 106936e030ebSStefano Zampini 107036e030ebSStefano Zampini PetscFunctionBegin; 107136e030ebSStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 10728687889aSStefano Zampini if (nvtxs) { 1073674ae819SStefano Zampini PetscValidIntPointer(xadj, 3); 10741633d1f0SStefano Zampini if (xadj[nvtxs]) PetscValidIntPointer(adjncy, 4); 10758687889aSStefano Zampini } 1076cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetLocalAdjacencyGraph_C", (PC, PetscInt, const PetscInt[], const PetscInt[], PetscCopyMode), (pc, nvtxs, xadj, adjncy, copymode)); 1077575ad6abSStefano Zampini /* free arrays if PCBDDC is not the PC type */ 10789566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", &f)); 1079575ad6abSStefano Zampini if (!f && copymode == PETSC_OWN_POINTER) { 10809566063dSJacob Faibussowitsch PetscCall(PetscFree(xadj)); 10819566063dSJacob Faibussowitsch PetscCall(PetscFree(adjncy)); 1082da1bb401SStefano Zampini } 108336e030ebSStefano Zampini PetscFunctionReturn(0); 108436e030ebSStefano Zampini } 10851e6b0712SBarry Smith 1086d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc, PetscInt n_is, IS ISForDofs[]) 1087d71ae5a4SJacob Faibussowitsch { 108863602bcaSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 108963602bcaSStefano Zampini PetscInt i; 109056282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 109163602bcaSStefano Zampini 109263602bcaSStefano Zampini PetscFunctionBegin; 109356282151SStefano Zampini if (pcbddc->n_ISForDofsLocal == n_is) { 109456282151SStefano Zampini for (i = 0; i < n_is; i++) { 109556282151SStefano Zampini PetscBool isequalt; 10969566063dSJacob Faibussowitsch PetscCall(ISEqual(ISForDofs[i], pcbddc->ISForDofsLocal[i], &isequalt)); 109756282151SStefano Zampini if (!isequalt) break; 109856282151SStefano Zampini } 109956282151SStefano Zampini if (i == n_is) isequal = PETSC_TRUE; 110056282151SStefano Zampini } 110148a46eb9SPierre Jolivet for (i = 0; i < n_is; i++) PetscCall(PetscObjectReference((PetscObject)ISForDofs[i])); 110263602bcaSStefano Zampini /* Destroy ISes if they were already set */ 110348a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_ISForDofsLocal; i++) PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i])); 11049566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofsLocal)); 1105a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 110648a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_ISForDofs; i++) PetscCall(ISDestroy(&pcbddc->ISForDofs[i])); 11079566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofs)); 110863602bcaSStefano Zampini pcbddc->n_ISForDofs = 0; 110963602bcaSStefano Zampini /* allocate space then set */ 111048a46eb9SPierre Jolivet if (n_is) PetscCall(PetscMalloc1(n_is, &pcbddc->ISForDofsLocal)); 1111ad540459SPierre Jolivet for (i = 0; i < n_is; i++) pcbddc->ISForDofsLocal[i] = ISForDofs[i]; 111263602bcaSStefano Zampini pcbddc->n_ISForDofsLocal = n_is; 111363602bcaSStefano Zampini if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE; 111456282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 111563602bcaSStefano Zampini PetscFunctionReturn(0); 111663602bcaSStefano Zampini } 111763602bcaSStefano Zampini 111863602bcaSStefano Zampini /*@ 111963602bcaSStefano Zampini PCBDDCSetDofsSplittingLocal - Set index sets defining fields of the local subdomain matrix 112063602bcaSStefano Zampini 112163602bcaSStefano Zampini Collective 112263602bcaSStefano Zampini 112363602bcaSStefano Zampini Input Parameters: 112463602bcaSStefano Zampini + pc - the preconditioning context 1125f1580f4eSBarry Smith . n_is - number of index sets defining the fields, must be the same on all MPI ranks 1126f1580f4eSBarry Smith - ISForDofs - array of `IS` describing the fields in local ordering 112763602bcaSStefano Zampini 112863602bcaSStefano Zampini Level: intermediate 112963602bcaSStefano Zampini 1130f1580f4eSBarry Smith Note: 1131f1580f4eSBarry Smith Not all nodes need to be listed: unlisted nodes will belong to the complement field. 113263602bcaSStefano Zampini 1133f1580f4eSBarry Smith .seealso: `PCBDDC`, `PCBDDCSetDofsSplitting()` 113463602bcaSStefano Zampini @*/ 1135d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc, PetscInt n_is, IS ISForDofs[]) 1136d71ae5a4SJacob Faibussowitsch { 113763602bcaSStefano Zampini PetscInt i; 113863602bcaSStefano Zampini 113963602bcaSStefano Zampini PetscFunctionBegin; 114063602bcaSStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 114163602bcaSStefano Zampini PetscValidLogicalCollectiveInt(pc, n_is, 2); 114263602bcaSStefano Zampini for (i = 0; i < n_is; i++) { 114363602bcaSStefano Zampini PetscCheckSameComm(pc, 1, ISForDofs[i], 3); 114463602bcaSStefano Zampini PetscValidHeaderSpecific(ISForDofs[i], IS_CLASSID, 3); 114563602bcaSStefano Zampini } 1146cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetDofsSplittingLocal_C", (PC, PetscInt, IS[]), (pc, n_is, ISForDofs)); 114763602bcaSStefano Zampini PetscFunctionReturn(0); 114863602bcaSStefano Zampini } 114963602bcaSStefano Zampini 1150d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc, PetscInt n_is, IS ISForDofs[]) 1151d71ae5a4SJacob Faibussowitsch { 11529c0446d6SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 11539c0446d6SStefano Zampini PetscInt i; 115456282151SStefano Zampini PetscBool isequal = PETSC_FALSE; 11559c0446d6SStefano Zampini 11569c0446d6SStefano Zampini PetscFunctionBegin; 115756282151SStefano Zampini if (pcbddc->n_ISForDofs == n_is) { 115856282151SStefano Zampini for (i = 0; i < n_is; i++) { 115956282151SStefano Zampini PetscBool isequalt; 11609566063dSJacob Faibussowitsch PetscCall(ISEqual(ISForDofs[i], pcbddc->ISForDofs[i], &isequalt)); 116156282151SStefano Zampini if (!isequalt) break; 116256282151SStefano Zampini } 116356282151SStefano Zampini if (i == n_is) isequal = PETSC_TRUE; 116456282151SStefano Zampini } 116548a46eb9SPierre Jolivet for (i = 0; i < n_is; i++) PetscCall(PetscObjectReference((PetscObject)ISForDofs[i])); 1166da1bb401SStefano Zampini /* Destroy ISes if they were already set */ 116748a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_ISForDofs; i++) PetscCall(ISDestroy(&pcbddc->ISForDofs[i])); 11689566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofs)); 1169a5b23f4aSJose E. Roman /* last user setting takes precedence -> destroy any other customization */ 117048a46eb9SPierre Jolivet for (i = 0; i < pcbddc->n_ISForDofsLocal; i++) PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i])); 11719566063dSJacob Faibussowitsch PetscCall(PetscFree(pcbddc->ISForDofsLocal)); 117263602bcaSStefano Zampini pcbddc->n_ISForDofsLocal = 0; 1173da1bb401SStefano Zampini /* allocate space then set */ 117448a46eb9SPierre Jolivet if (n_is) PetscCall(PetscMalloc1(n_is, &pcbddc->ISForDofs)); 1175ad540459SPierre Jolivet for (i = 0; i < n_is; i++) pcbddc->ISForDofs[i] = ISForDofs[i]; 11769c0446d6SStefano Zampini pcbddc->n_ISForDofs = n_is; 117763602bcaSStefano Zampini if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE; 117856282151SStefano Zampini if (!isequal) pcbddc->recompute_topography = PETSC_TRUE; 11799c0446d6SStefano Zampini PetscFunctionReturn(0); 11809c0446d6SStefano Zampini } 11811e6b0712SBarry Smith 11829c0446d6SStefano Zampini /*@ 118363602bcaSStefano Zampini PCBDDCSetDofsSplitting - Set index sets defining fields of the global matrix 11849c0446d6SStefano Zampini 118563602bcaSStefano Zampini Collective 11869c0446d6SStefano Zampini 11879c0446d6SStefano Zampini Input Parameters: 11889c0446d6SStefano Zampini + pc - the preconditioning context 11890f202f7eSStefano Zampini . n_is - number of index sets defining the fields 11900f202f7eSStefano Zampini - ISForDofs - array of IS describing the fields in global ordering 11919c0446d6SStefano Zampini 11929c0446d6SStefano Zampini Level: intermediate 11939c0446d6SStefano Zampini 1194f1580f4eSBarry Smith Note: 11950f202f7eSStefano Zampini Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field. 11969c0446d6SStefano Zampini 1197f1580f4eSBarry Smith .seealso: `PCBDDC`, `PCBDDCSetDofsSplittingLocal()` 11989c0446d6SStefano Zampini @*/ 1199d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDofsSplitting(PC pc, PetscInt n_is, IS ISForDofs[]) 1200d71ae5a4SJacob Faibussowitsch { 12012b510759SStefano Zampini PetscInt i; 12029c0446d6SStefano Zampini 12039c0446d6SStefano Zampini PetscFunctionBegin; 12049c0446d6SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 120563602bcaSStefano Zampini PetscValidLogicalCollectiveInt(pc, n_is, 2); 12062b510759SStefano Zampini for (i = 0; i < n_is; i++) { 120763602bcaSStefano Zampini PetscValidHeaderSpecific(ISForDofs[i], IS_CLASSID, 3); 1208a011d5a7Sstefano_zampini PetscCheckSameComm(pc, 1, ISForDofs[i], 3); 12092b510759SStefano Zampini } 1210cac4c232SBarry Smith PetscTryMethod(pc, "PCBDDCSetDofsSplitting_C", (PC, PetscInt, IS[]), (pc, n_is, ISForDofs)); 12119c0446d6SStefano Zampini PetscFunctionReturn(0); 12129c0446d6SStefano Zampini } 1213906d46d4SStefano Zampini 1214534831adSStefano Zampini /* 1215534831adSStefano Zampini PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial 1216534831adSStefano Zampini guess if a transformation of basis approach has been selected. 12179c0446d6SStefano Zampini 1218534831adSStefano Zampini Input Parameter: 1219966d8056SPierre Jolivet + pc - the preconditioner context 1220534831adSStefano Zampini 1221f1580f4eSBarry Smith Note: 1222534831adSStefano Zampini The interface routine PCPreSolve() is not usually called directly by 1223534831adSStefano Zampini the user, but instead is called by KSPSolve(). 1224534831adSStefano Zampini */ 1225d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x) 1226d71ae5a4SJacob Faibussowitsch { 1227534831adSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 1228534831adSStefano Zampini PC_IS *pcis = (PC_IS *)(pc->data); 12293972b0daSStefano Zampini Vec used_vec; 1230fcb54b1cSPierre Jolivet PetscBool iscg, save_rhs = PETSC_TRUE, benign_correction_computed; 1231534831adSStefano Zampini 1232534831adSStefano Zampini PetscFunctionBegin; 12331f4df5f7SStefano Zampini /* if we are working with CG, one dirichlet solve can be avoided during Krylov iterations */ 123485c4d303SStefano Zampini if (ksp) { 1235fcb54b1cSPierre Jolivet PetscCall(PetscObjectTypeCompareAny((PetscObject)ksp, &iscg, KSPCG, KSPGROPPCG, KSPPIPECG, KSPPIPELCG, KSPPIPECGRR, "")); 123648a46eb9SPierre Jolivet if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || !iscg || pc->mat != pc->pmat) PetscCall(PCBDDCSetUseExactDirichlet(pc, PETSC_FALSE)); 123785c4d303SStefano Zampini } 123848a46eb9SPierre Jolivet if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || pc->mat != pc->pmat) PetscCall(PCBDDCSetUseExactDirichlet(pc, PETSC_FALSE)); 12391f4df5f7SStefano Zampini 124085c4d303SStefano Zampini /* Creates parallel work vectors used in presolve */ 124148a46eb9SPierre Jolivet if (!pcbddc->original_rhs) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->original_rhs)); 124248a46eb9SPierre Jolivet if (!pcbddc->temp_solution) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->temp_solution)); 12438d00608fSStefano Zampini 124427b6a85dSStefano Zampini pcbddc->temp_solution_used = PETSC_FALSE; 12453972b0daSStefano Zampini if (x) { 12469566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)x)); 12473972b0daSStefano Zampini used_vec = x; 12488d00608fSStefano Zampini } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */ 12499566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)pcbddc->temp_solution)); 12503972b0daSStefano Zampini used_vec = pcbddc->temp_solution; 12519566063dSJacob Faibussowitsch PetscCall(VecSet(used_vec, 0.0)); 125227b6a85dSStefano Zampini pcbddc->temp_solution_used = PETSC_TRUE; 12539566063dSJacob Faibussowitsch PetscCall(VecCopy(rhs, pcbddc->original_rhs)); 1254266e20e9SStefano Zampini save_rhs = PETSC_FALSE; 1255266e20e9SStefano Zampini pcbddc->eliminate_dirdofs = PETSC_TRUE; 12563972b0daSStefano Zampini } 12578efcfb23SStefano Zampini 12588efcfb23SStefano Zampini /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */ 12593972b0daSStefano Zampini if (ksp) { 1260a0cb1b98SStefano Zampini /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */ 12619566063dSJacob Faibussowitsch PetscCall(KSPGetInitialGuessNonzero(ksp, &pcbddc->ksp_guess_nonzero)); 126248a46eb9SPierre Jolivet if (!pcbddc->ksp_guess_nonzero) PetscCall(VecSet(used_vec, 0.0)); 12633972b0daSStefano Zampini } 12643308cffdSStefano Zampini 12658d00608fSStefano Zampini pcbddc->rhs_change = PETSC_FALSE; 12663972b0daSStefano Zampini /* Take into account zeroed rows -> change rhs and store solution removed */ 126770c64980SStefano Zampini if (rhs && pcbddc->eliminate_dirdofs) { 12683975b054SStefano Zampini IS dirIS = NULL; 12693975b054SStefano Zampini 1270a07ea27aSStefano Zampini /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */ 12719566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph, &dirIS)); 12723975b054SStefano Zampini if (dirIS) { 1273906d46d4SStefano Zampini Mat_IS *matis = (Mat_IS *)pc->pmat->data; 1274785d1243SStefano Zampini PetscInt dirsize, i, *is_indices; 12752b095fd8SStefano Zampini PetscScalar *array_x; 12762b095fd8SStefano Zampini const PetscScalar *array_diagonal; 1277785d1243SStefano Zampini 12789566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(pc->pmat, pcis->vec1_global)); 12799566063dSJacob Faibussowitsch PetscCall(VecPointwiseDivide(pcis->vec1_global, rhs, pcis->vec1_global)); 12809566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_global, pcis->vec2_N, INSERT_VALUES, SCATTER_FORWARD)); 12819566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_global, pcis->vec2_N, INSERT_VALUES, SCATTER_FORWARD)); 12829566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, used_vec, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD)); 12839566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, used_vec, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD)); 12849566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(dirIS, &dirsize)); 12859566063dSJacob Faibussowitsch PetscCall(VecGetArray(pcis->vec1_N, &array_x)); 12869566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(pcis->vec2_N, &array_diagonal)); 12879566063dSJacob Faibussowitsch PetscCall(ISGetIndices(dirIS, (const PetscInt **)&is_indices)); 12882fa5cd67SKarl Rupp for (i = 0; i < dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]]; 12899566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(dirIS, (const PetscInt **)&is_indices)); 12909566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(pcis->vec2_N, &array_diagonal)); 12919566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pcis->vec1_N, &array_x)); 12929566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_N, used_vec, INSERT_VALUES, SCATTER_REVERSE)); 12939566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_N, used_vec, INSERT_VALUES, SCATTER_REVERSE)); 12948d00608fSStefano Zampini pcbddc->rhs_change = PETSC_TRUE; 12959566063dSJacob Faibussowitsch PetscCall(ISDestroy(&dirIS)); 12968efcfb23SStefano Zampini } 1297a07ea27aSStefano Zampini } 1298b76ba322SStefano Zampini 12998efcfb23SStefano Zampini /* remove the computed solution or the initial guess from the rhs */ 13008d00608fSStefano Zampini if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero)) { 130127b6a85dSStefano Zampini /* save the original rhs */ 130227b6a85dSStefano Zampini if (save_rhs) { 13039566063dSJacob Faibussowitsch PetscCall(VecSwap(rhs, pcbddc->original_rhs)); 130427b6a85dSStefano Zampini save_rhs = PETSC_FALSE; 13058d00608fSStefano Zampini } 13068d00608fSStefano Zampini pcbddc->rhs_change = PETSC_TRUE; 13079566063dSJacob Faibussowitsch PetscCall(VecScale(used_vec, -1.0)); 13089566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pc->mat, used_vec, pcbddc->original_rhs, rhs)); 13099566063dSJacob Faibussowitsch PetscCall(VecScale(used_vec, -1.0)); 13109566063dSJacob Faibussowitsch PetscCall(VecCopy(used_vec, pcbddc->temp_solution)); 131127b6a85dSStefano Zampini pcbddc->temp_solution_used = PETSC_TRUE; 13121baa6e33SBarry Smith if (ksp) PetscCall(KSPSetInitialGuessNonzero(ksp, PETSC_FALSE)); 13133308cffdSStefano Zampini } 13149566063dSJacob Faibussowitsch PetscCall(VecDestroy(&used_vec)); 1315b76ba322SStefano Zampini 1316fc17d649SStefano Zampini /* compute initial vector in benign space if needed 131727b6a85dSStefano Zampini and remove non-benign solution from the rhs */ 131827b6a85dSStefano Zampini benign_correction_computed = PETSC_FALSE; 131908af2428SStefano Zampini if (rhs && pcbddc->benign_compute_correction && (pcbddc->benign_have_null || pcbddc->benign_apply_coarse_only)) { 13201f4df5f7SStefano Zampini /* compute u^*_h using ideas similar to those in Xuemin Tu's PhD thesis (see Section 4.8.1) 13211f4df5f7SStefano Zampini Recursively apply BDDC in the multilevel case */ 132248a46eb9SPierre Jolivet if (!pcbddc->benign_vec) PetscCall(VecDuplicate(rhs, &pcbddc->benign_vec)); 1323c69e9cc1SStefano Zampini /* keep applying coarse solver unless we no longer have benign subdomains */ 1324c69e9cc1SStefano Zampini pcbddc->benign_apply_coarse_only = pcbddc->benign_have_null ? PETSC_TRUE : PETSC_FALSE; 132527b6a85dSStefano Zampini if (!pcbddc->benign_skip_correction) { 13269566063dSJacob Faibussowitsch PetscCall(PCApply_BDDC(pc, rhs, pcbddc->benign_vec)); 13273bca92a6SStefano Zampini benign_correction_computed = PETSC_TRUE; 13281baa6e33SBarry Smith if (pcbddc->temp_solution_used) PetscCall(VecAXPY(pcbddc->temp_solution, 1.0, pcbddc->benign_vec)); 13299566063dSJacob Faibussowitsch PetscCall(VecScale(pcbddc->benign_vec, -1.0)); 133027b6a85dSStefano Zampini /* store the original rhs if not done earlier */ 13311baa6e33SBarry Smith if (save_rhs) PetscCall(VecSwap(rhs, pcbddc->original_rhs)); 133227b6a85dSStefano Zampini if (pcbddc->rhs_change) { 13339566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pc->mat, pcbddc->benign_vec, rhs, rhs)); 133427b6a85dSStefano Zampini } else { 13359566063dSJacob Faibussowitsch PetscCall(MatMultAdd(pc->mat, pcbddc->benign_vec, pcbddc->original_rhs, rhs)); 133627b6a85dSStefano Zampini } 13370369aaf7SStefano Zampini pcbddc->rhs_change = PETSC_TRUE; 133827b6a85dSStefano Zampini } 133927b6a85dSStefano Zampini pcbddc->benign_apply_coarse_only = PETSC_FALSE; 13404df7a6bfSStefano Zampini } else { 13419566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->benign_vec)); 13420369aaf7SStefano Zampini } 13432d4c4fecSStefano Zampini 13442d4c4fecSStefano Zampini /* dbg output */ 1345a198735bSStefano Zampini if (pcbddc->dbg_flag && benign_correction_computed) { 13461f4df5f7SStefano Zampini Vec v; 1347c69e9cc1SStefano Zampini 13489566063dSJacob Faibussowitsch PetscCall(VecDuplicate(pcis->vec1_global, &v)); 1349c69e9cc1SStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 13509566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, rhs, v)); 1351c69e9cc1SStefano Zampini } else { 13529566063dSJacob Faibussowitsch PetscCall(VecCopy(rhs, v)); 1353c69e9cc1SStefano Zampini } 13549566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, v, PETSC_TRUE)); 135563a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "LEVEL %" PetscInt_FMT ": is the correction benign?\n", pcbddc->current_level)); 13569566063dSJacob Faibussowitsch PetscCall(PetscScalarView(pcbddc->benign_n, pcbddc->benign_p0, pcbddc->dbg_viewer)); 13579566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(pcbddc->dbg_viewer)); 13589566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 13591f4df5f7SStefano Zampini } 13600369aaf7SStefano Zampini 13610369aaf7SStefano Zampini /* set initial guess if using PCG */ 13628ae0ca82SStefano Zampini pcbddc->exact_dirichlet_trick_app = PETSC_FALSE; 13630369aaf7SStefano Zampini if (x && pcbddc->use_exact_dirichlet_trick) { 13649566063dSJacob Faibussowitsch PetscCall(VecSet(x, 0.0)); 13651dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) { 136627b6a85dSStefano Zampini if (benign_correction_computed) { /* we have already saved the changed rhs */ 13679566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(pcis->vec1_global)); 13681dd7afcfSStefano Zampini } else { 13699566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, rhs, pcis->vec1_global)); 13701dd7afcfSStefano Zampini } 13719566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_global, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 13729566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_global, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 13731dd7afcfSStefano Zampini } else { 13749566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, rhs, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 13759566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, rhs, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 13761dd7afcfSStefano Zampini } 13779566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 13789566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D)); 13799566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 13809566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D)); 13811dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) { 13829566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_global, 0.)); 13839566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, pcis->vec1_global, INSERT_VALUES, SCATTER_REVERSE)); 13849566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, pcis->vec1_global, INSERT_VALUES, SCATTER_REVERSE)); 13859566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcis->vec1_global, x)); 13861dd7afcfSStefano Zampini } else { 13879566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, x, INSERT_VALUES, SCATTER_REVERSE)); 13889566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, x, INSERT_VALUES, SCATTER_REVERSE)); 13891dd7afcfSStefano Zampini } 13901baa6e33SBarry Smith if (ksp) PetscCall(KSPSetInitialGuessNonzero(ksp, PETSC_TRUE)); 13918ae0ca82SStefano Zampini pcbddc->exact_dirichlet_trick_app = PETSC_TRUE; 1392266e20e9SStefano Zampini } else if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior && benign_correction_computed && pcbddc->use_exact_dirichlet_trick) { 13939566063dSJacob Faibussowitsch PetscCall(VecLockReadPop(pcis->vec1_global)); 13940369aaf7SStefano Zampini } 1395534831adSStefano Zampini PetscFunctionReturn(0); 1396534831adSStefano Zampini } 1397906d46d4SStefano Zampini 1398534831adSStefano Zampini /* 1399534831adSStefano Zampini PCPostSolve_BDDC - Changes the computed solution if a transformation of basis 1400534831adSStefano Zampini approach has been selected. Also, restores rhs to its original state. 1401534831adSStefano Zampini 1402534831adSStefano Zampini Input Parameter: 1403966d8056SPierre Jolivet + pc - the preconditioner context 1404534831adSStefano Zampini 1405534831adSStefano Zampini Application Interface Routine: PCPostSolve() 1406534831adSStefano Zampini 1407f1580f4eSBarry Smith Note: 1408534831adSStefano Zampini The interface routine PCPostSolve() is not usually called directly by 1409534831adSStefano Zampini the user, but instead is called by KSPSolve(). 1410534831adSStefano Zampini */ 1411d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x) 1412d71ae5a4SJacob Faibussowitsch { 1413534831adSStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 1414534831adSStefano Zampini 1415534831adSStefano Zampini PetscFunctionBegin; 14163972b0daSStefano Zampini /* add solution removed in presolve */ 14176bcfc461SStefano Zampini if (x && pcbddc->rhs_change) { 141827b6a85dSStefano Zampini if (pcbddc->temp_solution_used) { 14199566063dSJacob Faibussowitsch PetscCall(VecAXPY(x, 1.0, pcbddc->temp_solution)); 1420af140850Sstefano_zampini } else if (pcbddc->benign_compute_correction && pcbddc->benign_vec) { 14219566063dSJacob Faibussowitsch PetscCall(VecAXPY(x, -1.0, pcbddc->benign_vec)); 14223425bc38SStefano Zampini } 1423af140850Sstefano_zampini /* restore to original state (not for FETI-DP) */ 1424af140850Sstefano_zampini if (ksp) pcbddc->temp_solution_used = PETSC_FALSE; 142527b6a85dSStefano Zampini } 142627b6a85dSStefano Zampini 1427266e20e9SStefano Zampini /* restore rhs to its original state (not needed for FETI-DP) */ 14288d00608fSStefano Zampini if (rhs && pcbddc->rhs_change) { 14299566063dSJacob Faibussowitsch PetscCall(VecSwap(rhs, pcbddc->original_rhs)); 14308d00608fSStefano Zampini pcbddc->rhs_change = PETSC_FALSE; 1431af140850Sstefano_zampini } 14328efcfb23SStefano Zampini /* restore ksp guess state */ 14338efcfb23SStefano Zampini if (ksp) { 14349566063dSJacob Faibussowitsch PetscCall(KSPSetInitialGuessNonzero(ksp, pcbddc->ksp_guess_nonzero)); 14358ae0ca82SStefano Zampini /* reset flag for exact dirichlet trick */ 14368ae0ca82SStefano Zampini pcbddc->exact_dirichlet_trick_app = PETSC_FALSE; 1437af140850Sstefano_zampini } 1438534831adSStefano Zampini PetscFunctionReturn(0); 1439534831adSStefano Zampini } 1440af140850Sstefano_zampini 14410c7d97c5SJed Brown /* 14420c7d97c5SJed Brown PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner 14430c7d97c5SJed Brown by setting data structures and options. 14440c7d97c5SJed Brown 14450c7d97c5SJed Brown Input Parameter: 144653cdbc3dSStefano Zampini + pc - the preconditioner context 14470c7d97c5SJed Brown 14480c7d97c5SJed Brown Application Interface Routine: PCSetUp() 14490c7d97c5SJed Brown 1450f1580f4eSBarry Smith Note: 14510c7d97c5SJed Brown The interface routine PCSetUp() is not usually called directly by 14520c7d97c5SJed Brown the user, but instead is called by PCApply() if necessary. 14530c7d97c5SJed Brown */ 1454d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUp_BDDC(PC pc) 1455d71ae5a4SJacob Faibussowitsch { 14560c7d97c5SJed Brown PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 1457c703fcc7SStefano Zampini PCBDDCSubSchurs sub_schurs; 14585e8657edSStefano Zampini Mat_IS *matis; 145908122e43SStefano Zampini MatNullSpace nearnullspace; 146035509ce9Sstefano_zampini Mat lA; 146135509ce9Sstefano_zampini IS lP, zerodiag = NULL; 146291e8d312SStefano Zampini PetscInt nrows, ncols; 146386bfa4cfSStefano Zampini PetscMPIInt size; 1464c703fcc7SStefano Zampini PetscBool computesubschurs; 14658de1fae6SStefano Zampini PetscBool computeconstraintsmatrix; 14663b03f7bbSStefano Zampini PetscBool new_nearnullspace_provided, ismatis, rl; 1467b94d7dedSBarry Smith PetscBool isset, issym, isspd; 14680c7d97c5SJed Brown 14690c7d97c5SJed Brown PetscFunctionBegin; 14709566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATIS, &ismatis)); 147128b400f6SJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "PCBDDC preconditioner requires matrix of type MATIS"); 14729566063dSJacob Faibussowitsch PetscCall(MatGetSize(pc->pmat, &nrows, &ncols)); 14737827d75bSBarry Smith PetscCheck(nrows == ncols, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "PCBDDC preconditioner requires a square preconditioning matrix"); 14749566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size)); 147586bfa4cfSStefano Zampini 14765e8657edSStefano Zampini matis = (Mat_IS *)pc->pmat->data; 1477f4ddd8eeSStefano Zampini /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */ 14783b03a366Sstefano_zampini /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup 147971582508SStefano Zampini Also, BDDC builds its own KSP for the Dirichlet problem */ 14803b03f7bbSStefano Zampini rl = pcbddc->recompute_topography; 14813b03f7bbSStefano Zampini if (!pc->setupcalled || pc->flag == DIFFERENT_NONZERO_PATTERN) rl = PETSC_TRUE; 14821c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&rl, &pcbddc->recompute_topography, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc))); 1483c83e1ba7SStefano Zampini if (pcbddc->recompute_topography) { 1484c83e1ba7SStefano Zampini pcbddc->graphanalyzed = PETSC_FALSE; 1485c83e1ba7SStefano Zampini computeconstraintsmatrix = PETSC_TRUE; 1486c83e1ba7SStefano Zampini } else { 14878de1fae6SStefano Zampini computeconstraintsmatrix = PETSC_FALSE; 1488c83e1ba7SStefano Zampini } 1489b087196eSStefano Zampini 1490b087196eSStefano Zampini /* check parameters' compatibility */ 1491b7ab4a40SStefano Zampini if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE; 1492bd2a564bSStefano Zampini pcbddc->adaptive_selection = (PetscBool)(pcbddc->adaptive_threshold[0] != 0.0 || pcbddc->adaptive_threshold[1] != 0.0); 149386bfa4cfSStefano Zampini pcbddc->use_deluxe_scaling = (PetscBool)(pcbddc->use_deluxe_scaling && size > 1); 149486bfa4cfSStefano Zampini pcbddc->adaptive_selection = (PetscBool)(pcbddc->adaptive_selection && size > 1); 1495bf3a8328SStefano Zampini pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined); 1496862806e4SStefano Zampini if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE; 1497862806e4SStefano Zampini 14985a95e1ceSStefano Zampini computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling); 149916909a7fSStefano Zampini 150071582508SStefano Zampini /* activate all connected components if the netflux has been requested */ 1501bb05f991SStefano Zampini if (pcbddc->compute_nonetflux) { 1502bb05f991SStefano Zampini pcbddc->use_vertices = PETSC_TRUE; 1503bb05f991SStefano Zampini pcbddc->use_edges = PETSC_TRUE; 1504bb05f991SStefano Zampini pcbddc->use_faces = PETSC_TRUE; 1505bb05f991SStefano Zampini } 1506bb05f991SStefano Zampini 1507f4ddd8eeSStefano Zampini /* Get stdout for dbg */ 150870cf5478SStefano Zampini if (pcbddc->dbg_flag) { 1509ad540459SPierre Jolivet if (!pcbddc->dbg_viewer) pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc)); 15109566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer)); 15119566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIAddTab(pcbddc->dbg_viewer, 2 * pcbddc->current_level)); 1512f4ddd8eeSStefano Zampini } 1513f4ddd8eeSStefano Zampini 1514c703fcc7SStefano Zampini /* process topology information */ 15159566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Topology[pcbddc->current_level], pc, 0, 0, 0)); 151671582508SStefano Zampini if (pcbddc->recompute_topography) { 15179566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeLocalTopologyInfo(pc)); 15181baa6e33SBarry Smith if (pcbddc->discretegradient) PetscCall(PCBDDCNedelecSupport(pc)); 1519c703fcc7SStefano Zampini } 15204f819b78SStefano Zampini if (pcbddc->corner_selected) pcbddc->use_vertices = PETSC_TRUE; 1521a13144ffSStefano Zampini 1522c703fcc7SStefano Zampini /* change basis if requested by the user */ 15235e8657edSStefano Zampini if (pcbddc->user_ChangeOfBasisMatrix) { 15245e8657edSStefano Zampini /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */ 15255e8657edSStefano Zampini pcbddc->use_change_of_basis = PETSC_FALSE; 15269566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeLocalMatrix(pc, pcbddc->user_ChangeOfBasisMatrix)); 15275e8657edSStefano Zampini } else { 15289566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 15299566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)matis->A)); 15305e8657edSStefano Zampini pcbddc->local_mat = matis->A; 1531d16cbb6bSStefano Zampini } 1532d16cbb6bSStefano Zampini 15334f1b2e48SStefano Zampini /* 1534c703fcc7SStefano Zampini Compute change of basis on local pressures (aka zerodiag dofs) with the benign trick 15354f1b2e48SStefano Zampini This should come earlier then PCISSetUp for extracting the correct subdomain matrices 15364f1b2e48SStefano Zampini */ 15379566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignShellMat(pc, PETSC_TRUE)); 1538d16cbb6bSStefano Zampini if (pcbddc->benign_saddle_point) { 15399f47a83aSStefano Zampini PC_IS *pcis = (PC_IS *)pc->data; 15409f47a83aSStefano Zampini 154105b28244SStefano Zampini if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE; 15423b03f7bbSStefano Zampini /* detect local saddle point and change the basis in pcbddc->local_mat */ 15439566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignDetectSaddlePoint(pc, (PetscBool)(!pcbddc->recompute_topography), &zerodiag)); 1544a3df083aSStefano Zampini /* pop B0 mat from local mat */ 15459566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignPopOrPushB0(pc, PETSC_TRUE)); 15461dd7afcfSStefano Zampini /* give pcis a hint to not reuse submatrices during PCISCreate */ 15471dd7afcfSStefano Zampini if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) { 15481dd7afcfSStefano Zampini if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) { 15491dd7afcfSStefano Zampini pcis->reusesubmatrices = PETSC_FALSE; 15501dd7afcfSStefano Zampini } else { 1551a3df083aSStefano Zampini pcis->reusesubmatrices = PETSC_TRUE; 15521dd7afcfSStefano Zampini } 1553a3df083aSStefano Zampini } else { 15549f47a83aSStefano Zampini pcis->reusesubmatrices = PETSC_FALSE; 1555674ae819SStefano Zampini } 1556a3df083aSStefano Zampini } 155727b6a85dSStefano Zampini 15588037d520SStefano Zampini /* propagate relevant information */ 1559b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(matis->A, &isset, &issym)); 1560b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(pcbddc->local_mat, MAT_SYMMETRIC, issym)); 1561b94d7dedSBarry Smith PetscCall(MatIsSPDKnown(matis->A, &isset, &isspd)); 1562b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(pcbddc->local_mat, MAT_SPD, isspd)); 1563e496cd5dSStefano Zampini 15645e8657edSStefano Zampini /* Set up all the "iterative substructuring" common block without computing solvers */ 15655e8657edSStefano Zampini { 15665e8657edSStefano Zampini Mat temp_mat; 15675e8657edSStefano Zampini 15685e8657edSStefano Zampini temp_mat = matis->A; 15695e8657edSStefano Zampini matis->A = pcbddc->local_mat; 15709566063dSJacob Faibussowitsch PetscCall(PCISSetUp(pc, PETSC_TRUE, PETSC_FALSE)); 15715e8657edSStefano Zampini pcbddc->local_mat = matis->A; 15725e8657edSStefano Zampini matis->A = temp_mat; 15735e8657edSStefano Zampini } 1574684f6988SStefano Zampini 157581d14e9dSStefano Zampini /* Analyze interface */ 157664ac59b8SStefano Zampini if (!pcbddc->graphanalyzed) { 15779566063dSJacob Faibussowitsch PetscCall(PCBDDCAnalyzeInterface(pc)); 15788de1fae6SStefano Zampini computeconstraintsmatrix = PETSC_TRUE; 1579345ecf6cSStefano Zampini if (pcbddc->adaptive_selection && !pcbddc->use_deluxe_scaling && !pcbddc->mat_graph->twodim) { 15804247aa23Sstefano_zampini SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot compute the adaptive primal space for a problem with 3D edges without deluxe scaling"); 1581345ecf6cSStefano Zampini } 1582a198735bSStefano Zampini if (pcbddc->compute_nonetflux) { 1583669cc0f4SStefano Zampini MatNullSpace nnfnnsp; 1584669cc0f4SStefano Zampini 158528b400f6SJacob Faibussowitsch PetscCheck(pcbddc->divudotp, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Missing divudotp operator"); 15869566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeNoNetFlux(pc->pmat, pcbddc->divudotp, pcbddc->divudotp_trans, pcbddc->divudotp_vl2l, pcbddc->mat_graph, &nnfnnsp)); 158771582508SStefano Zampini /* TODO what if a nearnullspace is already attached? */ 15888037d520SStefano Zampini if (nnfnnsp) { 15899566063dSJacob Faibussowitsch PetscCall(MatSetNearNullSpace(pc->pmat, nnfnnsp)); 15909566063dSJacob Faibussowitsch PetscCall(MatNullSpaceDestroy(&nnfnnsp)); 1591669cc0f4SStefano Zampini } 1592674ae819SStefano Zampini } 15938037d520SStefano Zampini } 15949566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Topology[pcbddc->current_level], pc, 0, 0, 0)); 1595fb8d54d4SStefano Zampini 15965408967cSStefano Zampini /* check existence of a divergence free extension, i.e. 15975408967cSStefano Zampini b(v_I,p_0) = 0 for all v_I (raise error if not). 15985408967cSStefano Zampini Also, check that PCBDDCBenignGetOrSetP0 works */ 159948a46eb9SPierre Jolivet if (pcbddc->benign_saddle_point && pcbddc->dbg_flag > 1) PetscCall(PCBDDCBenignCheck(pc, zerodiag)); 16009566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zerodiag)); 160106f24817SStefano Zampini 1602b96c3477SStefano Zampini /* Setup local dirichlet solver ksp_D and sub_schurs solvers */ 160348a46eb9SPierre Jolivet if (computesubschurs && pcbddc->recompute_topography) PetscCall(PCBDDCInitSubSchurs(pc)); 16049d54b7f4SStefano Zampini /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/ 160548a46eb9SPierre Jolivet if (!pcbddc->use_deluxe_scaling) PetscCall(PCBDDCScalingSetUp(pc)); 1606c703fcc7SStefano Zampini 1607c703fcc7SStefano Zampini /* finish setup solvers and do adaptive selection of constraints */ 1608b334f244SStefano Zampini sub_schurs = pcbddc->sub_schurs; 1609b334f244SStefano Zampini if (sub_schurs && sub_schurs->schur_explicit) { 16101baa6e33SBarry Smith if (computesubschurs) PetscCall(PCBDDCSetUpSubSchurs(pc)); 16119566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalSolvers(pc, PETSC_TRUE, PETSC_FALSE)); 1612d5574798SStefano Zampini } else { 16139566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalSolvers(pc, PETSC_TRUE, PETSC_FALSE)); 16141baa6e33SBarry Smith if (computesubschurs) PetscCall(PCBDDCSetUpSubSchurs(pc)); 16152070dbb6SStefano Zampini } 161608122e43SStefano Zampini if (pcbddc->adaptive_selection) { 16179566063dSJacob Faibussowitsch PetscCall(PCBDDCAdaptiveSelection(pc)); 16188de1fae6SStefano Zampini computeconstraintsmatrix = PETSC_TRUE; 1619b7eb3628SStefano Zampini } 1620684f6988SStefano Zampini 1621f4ddd8eeSStefano Zampini /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */ 1622fb8d54d4SStefano Zampini new_nearnullspace_provided = PETSC_FALSE; 16239566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(pc->pmat, &nearnullspace)); 1624f4ddd8eeSStefano Zampini if (pcbddc->onearnullspace) { /* already used nearnullspace */ 1625f4ddd8eeSStefano Zampini if (!nearnullspace) { /* near null space attached to mat has been destroyed */ 1626f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_TRUE; 1627f4ddd8eeSStefano Zampini } else { 1628f4ddd8eeSStefano Zampini /* determine if the two nullspaces are different (should be lightweight) */ 1629f4ddd8eeSStefano Zampini if (nearnullspace != pcbddc->onearnullspace) { 1630f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_TRUE; 1631165b64e2SStefano Zampini } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */ 1632f4ddd8eeSStefano Zampini PetscInt i; 1633165b64e2SStefano Zampini const Vec *nearnullvecs; 1634165b64e2SStefano Zampini PetscObjectState state; 1635165b64e2SStefano Zampini PetscInt nnsp_size; 16369566063dSJacob Faibussowitsch PetscCall(MatNullSpaceGetVecs(nearnullspace, NULL, &nnsp_size, &nearnullvecs)); 1637f4ddd8eeSStefano Zampini for (i = 0; i < nnsp_size; i++) { 16389566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)nearnullvecs[i], &state)); 1639165b64e2SStefano Zampini if (pcbddc->onearnullvecs_state[i] != state) { 1640f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_TRUE; 1641f4ddd8eeSStefano Zampini break; 1642f4ddd8eeSStefano Zampini } 1643f4ddd8eeSStefano Zampini } 1644f4ddd8eeSStefano Zampini } 1645f4ddd8eeSStefano Zampini } 1646f4ddd8eeSStefano Zampini } else { 1647f4ddd8eeSStefano Zampini if (!nearnullspace) { /* both nearnullspaces are null */ 1648f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_FALSE; 1649f4ddd8eeSStefano Zampini } else { /* nearnullspace attached later */ 1650f4ddd8eeSStefano Zampini new_nearnullspace_provided = PETSC_TRUE; 1651f4ddd8eeSStefano Zampini } 1652f4ddd8eeSStefano Zampini } 1653f4ddd8eeSStefano Zampini 1654f4ddd8eeSStefano Zampini /* Setup constraints and related work vectors */ 1655727cdba6SStefano Zampini /* reset primal space flags */ 16569566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_LocalWork[pcbddc->current_level], pc, 0, 0, 0)); 1657f4ddd8eeSStefano Zampini pcbddc->new_primal_space = PETSC_FALSE; 1658727cdba6SStefano Zampini pcbddc->new_primal_space_local = PETSC_FALSE; 16598de1fae6SStefano Zampini if (computeconstraintsmatrix || new_nearnullspace_provided) { 1660727cdba6SStefano Zampini /* It also sets the primal space flags */ 16619566063dSJacob Faibussowitsch PetscCall(PCBDDCConstraintsSetUp(pc)); 16629543d0ffSStefano Zampini } 1663e7b262bdSStefano Zampini /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */ 16649566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpLocalWorkVectors(pc)); 16655e8657edSStefano Zampini 16665e8657edSStefano Zampini if (pcbddc->use_change_of_basis) { 16675e8657edSStefano Zampini PC_IS *pcis = (PC_IS *)(pc->data); 16685e8657edSStefano Zampini 16699566063dSJacob Faibussowitsch PetscCall(PCBDDCComputeLocalMatrix(pc, pcbddc->ChangeOfBasisMatrix)); 16704f1b2e48SStefano Zampini if (pcbddc->benign_change) { 16719566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->benign_B0)); 1672c263805aSStefano Zampini /* pop B0 from pcbddc->local_mat */ 16739566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignPopOrPushB0(pc, PETSC_TRUE)); 1674c263805aSStefano Zampini } 16755e8657edSStefano Zampini /* get submatrices */ 16769566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_IB)); 16779566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_BI)); 16789566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcis->A_BB)); 16799566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_B_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &pcis->A_BB)); 16809566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_I_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &pcis->A_IB)); 16819566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_B_local, pcis->is_I_local, MAT_INITIAL_MATRIX, &pcis->A_BI)); 16823975b054SStefano Zampini /* set flag in pcis to not reuse submatrices during PCISCreate */ 16833975b054SStefano Zampini pcis->reusesubmatrices = PETSC_FALSE; 16849c6a02ceSStefano Zampini } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) { 16859566063dSJacob Faibussowitsch PetscCall(MatDestroy(&pcbddc->local_mat)); 16869566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)matis->A)); 16875e8657edSStefano Zampini pcbddc->local_mat = matis->A; 16885e8657edSStefano Zampini } 168935509ce9Sstefano_zampini 169035509ce9Sstefano_zampini /* interface pressure block row for B_C */ 16919566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lP", (PetscObject *)&lP)); 16929566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lA", (PetscObject *)&lA)); 169335509ce9Sstefano_zampini if (lA && lP) { 169435509ce9Sstefano_zampini PC_IS *pcis = (PC_IS *)pc->data; 169535509ce9Sstefano_zampini Mat B_BI, B_BB, Bt_BI, Bt_BB; 169635509ce9Sstefano_zampini PetscBool issym; 1697b94d7dedSBarry Smith 16989566063dSJacob Faibussowitsch PetscCall(MatIsSymmetric(lA, PETSC_SMALL, &issym)); 16996cc1294bSstefano_zampini if (issym) { 17009566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_I_local, MAT_INITIAL_MATRIX, &B_BI)); 17019566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_B_local, MAT_INITIAL_MATRIX, &B_BB)); 17029566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(B_BI, &Bt_BI)); 17039566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(B_BB, &Bt_BB)); 170435509ce9Sstefano_zampini } else { 17059566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_I_local, MAT_INITIAL_MATRIX, &B_BI)); 17069566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_B_local, MAT_INITIAL_MATRIX, &B_BB)); 17079566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA, pcis->is_I_local, lP, MAT_INITIAL_MATRIX, &Bt_BI)); 17089566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(lA, pcis->is_B_local, lP, MAT_INITIAL_MATRIX, &Bt_BB)); 170935509ce9Sstefano_zampini } 17109566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_B_BI", (PetscObject)B_BI)); 17119566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_B_BB", (PetscObject)B_BB)); 17129566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_Bt_BI", (PetscObject)Bt_BI)); 17139566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_Bt_BB", (PetscObject)Bt_BB)); 17149566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B_BI)); 17159566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B_BB)); 17169566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bt_BI)); 17179566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Bt_BB)); 171835509ce9Sstefano_zampini } 17199566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_LocalWork[pcbddc->current_level], pc, 0, 0, 0)); 172035509ce9Sstefano_zampini 1721b96c3477SStefano Zampini /* SetUp coarse and local Neumann solvers */ 17229566063dSJacob Faibussowitsch PetscCall(PCBDDCSetUpSolvers(pc)); 1723b96c3477SStefano Zampini /* SetUp Scaling operator */ 17241baa6e33SBarry Smith if (pcbddc->use_deluxe_scaling) PetscCall(PCBDDCScalingSetUp(pc)); 1725c703fcc7SStefano Zampini 17261dd7afcfSStefano Zampini /* mark topography as done */ 172756282151SStefano Zampini pcbddc->recompute_topography = PETSC_FALSE; 17280369aaf7SStefano Zampini 17291dd7afcfSStefano Zampini /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */ 17309566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignShellMat(pc, PETSC_FALSE)); 17311dd7afcfSStefano Zampini 173258a03d70SStefano Zampini if (pcbddc->dbg_flag) { 17339566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISubtractTab(pcbddc->dbg_viewer, 2 * pcbddc->current_level)); 17349566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer)); 17352b510759SStefano Zampini } 17360c7d97c5SJed Brown PetscFunctionReturn(0); 17370c7d97c5SJed Brown } 17380c7d97c5SJed Brown 17390c7d97c5SJed Brown /* 174050efa1b5SStefano Zampini PCApply_BDDC - Applies the BDDC operator to a vector. 17410c7d97c5SJed Brown 17420c7d97c5SJed Brown Input Parameters: 17430f202f7eSStefano Zampini + pc - the preconditioner context 17440f202f7eSStefano Zampini - r - input vector (global) 17450c7d97c5SJed Brown 17460c7d97c5SJed Brown Output Parameter: 17470c7d97c5SJed Brown . z - output vector (global) 17480c7d97c5SJed Brown 17490c7d97c5SJed Brown Application Interface Routine: PCApply() 17500c7d97c5SJed Brown */ 1751d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApply_BDDC(PC pc, Vec r, Vec z) 1752d71ae5a4SJacob Faibussowitsch { 17530c7d97c5SJed Brown PC_IS *pcis = (PC_IS *)(pc->data); 17540c7d97c5SJed Brown PC_BDDC *pcbddc = (PC_BDDC *)(pc->data); 1755b3338236SStefano Zampini Mat lA = NULL; 1756b097fa66SStefano Zampini PetscInt n_B = pcis->n_B, n_D = pcis->n - n_B; 17573b03a366Sstefano_zampini const PetscScalar one = 1.0; 17583b03a366Sstefano_zampini const PetscScalar m_one = -1.0; 17592617d88aSStefano Zampini const PetscScalar zero = 0.0; 17600c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN 17610c7d97c5SJed Brown NN interface preconditioner changed to BDDC 1762b097fa66SStefano Zampini Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */ 17630c7d97c5SJed Brown 17640c7d97c5SJed Brown PetscFunctionBegin; 17659566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(citation, &cited)); 176648a46eb9SPierre Jolivet if (pcbddc->switch_static) PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat, &lA)); 1767b3338236SStefano Zampini 17681dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 17691dd7afcfSStefano Zampini Vec swap; 177027b6a85dSStefano Zampini 17719566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, r, pcbddc->work_change)); 17721dd7afcfSStefano Zampini swap = pcbddc->work_change; 17731dd7afcfSStefano Zampini pcbddc->work_change = r; 17741dd7afcfSStefano Zampini r = swap; 17751dd7afcfSStefano Zampini /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */ 17769cc2a9b1Sstefano_zampini if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) { 17779566063dSJacob Faibussowitsch PetscCall(VecCopy(r, pcis->vec1_global)); 17789566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(pcis->vec1_global)); 17791dd7afcfSStefano Zampini } 17801dd7afcfSStefano Zampini } 178127b6a85dSStefano Zampini if (pcbddc->benign_have_null) { /* get p0 from r */ 17829566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, r, PETSC_TRUE)); 1783efc2fbd9SStefano Zampini } 1784bc960bbfSJed Brown if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET && !pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) { 17859566063dSJacob Faibussowitsch PetscCall(VecCopy(r, z)); 17860c7d97c5SJed Brown /* First Dirichlet solve */ 17879566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 17889566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 17890c7d97c5SJed Brown /* 17900c7d97c5SJed Brown Assembling right hand side for BDDC operator 1791b097fa66SStefano Zampini - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE) 1792674ae819SStefano Zampini - pcis->vec1_B the interface part of the global vector z 17930c7d97c5SJed Brown */ 1794b097fa66SStefano Zampini if (n_D) { 17959566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 17969566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D)); 17979566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 17989566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D)); 17999566063dSJacob Faibussowitsch PetscCall(VecScale(pcis->vec2_D, m_one)); 180016909a7fSStefano Zampini if (pcbddc->switch_static) { 18019566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_N, 0.)); 18029566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 18039566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 180416909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 18059566063dSJacob Faibussowitsch PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N)); 180616909a7fSStefano Zampini } else { 18079566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N)); 18089566063dSJacob Faibussowitsch PetscCall(MatMult(lA, pcis->vec2_N, pcis->vec1_N)); 18099566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N)); 181016909a7fSStefano Zampini } 18119566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD)); 18129566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD)); 18139566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 18149566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 181516909a7fSStefano Zampini } else { 18169566063dSJacob Faibussowitsch PetscCall(MatMult(pcis->A_BI, pcis->vec2_D, pcis->vec1_B)); 181716909a7fSStefano Zampini } 1818b097fa66SStefano Zampini } else { 18199566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_B, zero)); 1820b097fa66SStefano Zampini } 18219566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE)); 18229566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE)); 18239566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(pc, z, pcis->vec1_B)); 1824b76ba322SStefano Zampini } else { 182548a46eb9SPierre Jolivet if (!pcbddc->benign_apply_coarse_only) PetscCall(PCBDDCScalingRestriction(pc, r, pcis->vec1_B)); 18264fee134fSStefano Zampini } 1827bc960bbfSJed Brown if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) { 182828b400f6SJacob Faibussowitsch PetscCheck(pcbddc->switch_static, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "You forgot to pass -pc_bddc_switch_static"); 18299566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 18309566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 1831bc960bbfSJed Brown } 1832b76ba322SStefano Zampini 18332617d88aSStefano Zampini /* Apply interface preconditioner 18342617d88aSStefano Zampini input/output vecs: pcis->vec1_B and pcis->vec1_D */ 18359566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(pc, PETSC_FALSE)); 18362617d88aSStefano Zampini 1837674ae819SStefano Zampini /* Apply transpose of partition of unity operator */ 18389566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingExtension(pc, pcis->vec1_B, z)); 1839bc960bbfSJed Brown if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) { 18409566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_D, z, INSERT_VALUES, SCATTER_REVERSE)); 18419566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_D, z, INSERT_VALUES, SCATTER_REVERSE)); 1842bc960bbfSJed Brown PetscFunctionReturn(0); 1843bc960bbfSJed Brown } 18443b03a366Sstefano_zampini /* Second Dirichlet solve and assembling of output */ 18459566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 18469566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 1847b097fa66SStefano Zampini if (n_B) { 184816909a7fSStefano Zampini if (pcbddc->switch_static) { 18499566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 18509566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 18519566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 18529566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 185316909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 18549566063dSJacob Faibussowitsch PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N)); 185516909a7fSStefano Zampini } else { 18569566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N)); 18579566063dSJacob Faibussowitsch PetscCall(MatMult(lA, pcis->vec2_N, pcis->vec1_N)); 18589566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N)); 185916909a7fSStefano Zampini } 18609566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD)); 18619566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD)); 186216909a7fSStefano Zampini } else { 18639566063dSJacob Faibussowitsch PetscCall(MatMult(pcis->A_IB, pcis->vec1_B, pcis->vec3_D)); 186416909a7fSStefano Zampini } 186516909a7fSStefano Zampini } else if (pcbddc->switch_static) { /* n_B is zero */ 186616909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 18679566063dSJacob Faibussowitsch PetscCall(MatMult(lA, pcis->vec1_D, pcis->vec3_D)); 186816909a7fSStefano Zampini } else { 18699566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_D, pcis->vec1_N)); 18709566063dSJacob Faibussowitsch PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N)); 18719566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec2_N, pcis->vec3_D)); 187216909a7fSStefano Zampini } 1873b097fa66SStefano Zampini } 18749566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 18759566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec3_D, pcis->vec4_D)); 18769566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 18779566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec4_D)); 1878efc2fbd9SStefano Zampini 18798ae0ca82SStefano Zampini if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) { 1880b097fa66SStefano Zampini if (pcbddc->switch_static) { 18819566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(pcis->vec2_D, m_one, one, m_one, pcis->vec4_D, pcis->vec1_D)); 1882b097fa66SStefano Zampini } else { 18839566063dSJacob Faibussowitsch PetscCall(VecAXPBY(pcis->vec2_D, m_one, m_one, pcis->vec4_D)); 1884b097fa66SStefano Zampini } 18859566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE)); 18869566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE)); 1887b097fa66SStefano Zampini } else { 1888b097fa66SStefano Zampini if (pcbddc->switch_static) { 18899566063dSJacob Faibussowitsch PetscCall(VecAXPBY(pcis->vec4_D, one, m_one, pcis->vec1_D)); 1890b097fa66SStefano Zampini } else { 18919566063dSJacob Faibussowitsch PetscCall(VecScale(pcis->vec4_D, m_one)); 1892b097fa66SStefano Zampini } 18939566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE)); 18949566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE)); 1895b097fa66SStefano Zampini } 189627b6a85dSStefano Zampini if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */ 18971baa6e33SBarry Smith if (pcbddc->benign_apply_coarse_only) PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n)); 18989566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, z, PETSC_FALSE)); 1899efc2fbd9SStefano Zampini } 19001f4df5f7SStefano Zampini 19011dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 1902f913dca9SStefano Zampini pcbddc->work_change = r; 19039566063dSJacob Faibussowitsch PetscCall(VecCopy(z, pcbddc->work_change)); 19049566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcbddc->work_change, z)); 19051dd7afcfSStefano Zampini } 19060c7d97c5SJed Brown PetscFunctionReturn(0); 19070c7d97c5SJed Brown } 190850efa1b5SStefano Zampini 190950efa1b5SStefano Zampini /* 191050efa1b5SStefano Zampini PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector. 191150efa1b5SStefano Zampini 191250efa1b5SStefano Zampini Input Parameters: 19130f202f7eSStefano Zampini + pc - the preconditioner context 19140f202f7eSStefano Zampini - r - input vector (global) 191550efa1b5SStefano Zampini 191650efa1b5SStefano Zampini Output Parameter: 191750efa1b5SStefano Zampini . z - output vector (global) 191850efa1b5SStefano Zampini 191950efa1b5SStefano Zampini Application Interface Routine: PCApplyTranspose() 192050efa1b5SStefano Zampini */ 1921d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApplyTranspose_BDDC(PC pc, Vec r, Vec z) 1922d71ae5a4SJacob Faibussowitsch { 192350efa1b5SStefano Zampini PC_IS *pcis = (PC_IS *)(pc->data); 192450efa1b5SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)(pc->data); 1925b3338236SStefano Zampini Mat lA = NULL; 1926b097fa66SStefano Zampini PetscInt n_B = pcis->n_B, n_D = pcis->n - n_B; 192750efa1b5SStefano Zampini const PetscScalar one = 1.0; 192850efa1b5SStefano Zampini const PetscScalar m_one = -1.0; 192950efa1b5SStefano Zampini const PetscScalar zero = 0.0; 193050efa1b5SStefano Zampini 193150efa1b5SStefano Zampini PetscFunctionBegin; 19329566063dSJacob Faibussowitsch PetscCall(PetscCitationsRegister(citation, &cited)); 193348a46eb9SPierre Jolivet if (pcbddc->switch_static) PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat, &lA)); 19341dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 19351dd7afcfSStefano Zampini Vec swap; 193627b6a85dSStefano Zampini 19379566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, r, pcbddc->work_change)); 19381dd7afcfSStefano Zampini swap = pcbddc->work_change; 19391dd7afcfSStefano Zampini pcbddc->work_change = r; 19401dd7afcfSStefano Zampini r = swap; 194127b6a85dSStefano Zampini /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */ 19428ae0ca82SStefano Zampini if (pcbddc->benign_apply_coarse_only && pcbddc->exact_dirichlet_trick_app && pcbddc->change_interior) { 19439566063dSJacob Faibussowitsch PetscCall(VecCopy(r, pcis->vec1_global)); 19449566063dSJacob Faibussowitsch PetscCall(VecLockReadPush(pcis->vec1_global)); 19451dd7afcfSStefano Zampini } 194627b6a85dSStefano Zampini } 194727b6a85dSStefano Zampini if (pcbddc->benign_have_null) { /* get p0 from r */ 19489566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, r, PETSC_TRUE)); 1949537c1cdfSStefano Zampini } 19508ae0ca82SStefano Zampini if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) { 19519566063dSJacob Faibussowitsch PetscCall(VecCopy(r, z)); 195250efa1b5SStefano Zampini /* First Dirichlet solve */ 19539566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 19549566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD)); 195550efa1b5SStefano Zampini /* 195650efa1b5SStefano Zampini Assembling right hand side for BDDC operator 1957b097fa66SStefano Zampini - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE) 195850efa1b5SStefano Zampini - pcis->vec1_B the interface part of the global vector z 195950efa1b5SStefano Zampini */ 1960b097fa66SStefano Zampini if (n_D) { 19619566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 19629566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D)); 19639566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 19649566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D)); 19659566063dSJacob Faibussowitsch PetscCall(VecScale(pcis->vec2_D, m_one)); 196616909a7fSStefano Zampini if (pcbddc->switch_static) { 19679566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_N, 0.)); 19689566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 19699566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 197016909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 19719566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N)); 197216909a7fSStefano Zampini } else { 19739566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N)); 19749566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA, pcis->vec2_N, pcis->vec1_N)); 19759566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N)); 197616909a7fSStefano Zampini } 19779566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD)); 19789566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD)); 19799566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 19809566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 198116909a7fSStefano Zampini } else { 19829566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcis->A_IB, pcis->vec2_D, pcis->vec1_B)); 198316909a7fSStefano Zampini } 1984b097fa66SStefano Zampini } else { 19859566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_B, zero)); 1986b097fa66SStefano Zampini } 19879566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE)); 19889566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE)); 19899566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(pc, z, pcis->vec1_B)); 199050efa1b5SStefano Zampini } else { 19919566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(pc, r, pcis->vec1_B)); 199250efa1b5SStefano Zampini } 199350efa1b5SStefano Zampini 199450efa1b5SStefano Zampini /* Apply interface preconditioner 199550efa1b5SStefano Zampini input/output vecs: pcis->vec1_B and pcis->vec1_D */ 19969566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(pc, PETSC_TRUE)); 199750efa1b5SStefano Zampini 199850efa1b5SStefano Zampini /* Apply transpose of partition of unity operator */ 19999566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingExtension(pc, pcis->vec1_B, z)); 200050efa1b5SStefano Zampini 200150efa1b5SStefano Zampini /* Second Dirichlet solve and assembling of output */ 20029566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 20039566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD)); 2004b097fa66SStefano Zampini if (n_B) { 200516909a7fSStefano Zampini if (pcbddc->switch_static) { 20069566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 20079566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 20089566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 20099566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE)); 201016909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 20119566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N)); 201216909a7fSStefano Zampini } else { 20139566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N)); 20149566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA, pcis->vec2_N, pcis->vec1_N)); 20159566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N)); 201616909a7fSStefano Zampini } 20179566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD)); 20189566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD)); 201916909a7fSStefano Zampini } else { 20209566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcis->A_BI, pcis->vec1_B, pcis->vec3_D)); 202116909a7fSStefano Zampini } 202216909a7fSStefano Zampini } else if (pcbddc->switch_static) { /* n_B is zero */ 202316909a7fSStefano Zampini if (!pcbddc->switch_static_change) { 20249566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA, pcis->vec1_D, pcis->vec3_D)); 202516909a7fSStefano Zampini } else { 20269566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_D, pcis->vec1_N)); 20279566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N)); 20289566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec2_N, pcis->vec3_D)); 202916909a7fSStefano Zampini } 2030b097fa66SStefano Zampini } 20319566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 20329566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(pcbddc->ksp_D, pcis->vec3_D, pcis->vec4_D)); 20339566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0)); 20349566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec4_D)); 20358ae0ca82SStefano Zampini if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) { 2036b097fa66SStefano Zampini if (pcbddc->switch_static) { 20379566063dSJacob Faibussowitsch PetscCall(VecAXPBYPCZ(pcis->vec2_D, m_one, one, m_one, pcis->vec4_D, pcis->vec1_D)); 2038b097fa66SStefano Zampini } else { 20399566063dSJacob Faibussowitsch PetscCall(VecAXPBY(pcis->vec2_D, m_one, m_one, pcis->vec4_D)); 2040b097fa66SStefano Zampini } 20419566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE)); 20429566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE)); 2043b097fa66SStefano Zampini } else { 2044b097fa66SStefano Zampini if (pcbddc->switch_static) { 20459566063dSJacob Faibussowitsch PetscCall(VecAXPBY(pcis->vec4_D, one, m_one, pcis->vec1_D)); 2046b097fa66SStefano Zampini } else { 20479566063dSJacob Faibussowitsch PetscCall(VecScale(pcis->vec4_D, m_one)); 2048b097fa66SStefano Zampini } 20499566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE)); 20509566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE)); 2051b097fa66SStefano Zampini } 205227b6a85dSStefano Zampini if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */ 20539566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(pc, z, PETSC_FALSE)); 2054537c1cdfSStefano Zampini } 20551dd7afcfSStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 2056f913dca9SStefano Zampini pcbddc->work_change = r; 20579566063dSJacob Faibussowitsch PetscCall(VecCopy(z, pcbddc->work_change)); 20589566063dSJacob Faibussowitsch PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcbddc->work_change, z)); 20591dd7afcfSStefano Zampini } 206050efa1b5SStefano Zampini PetscFunctionReturn(0); 206150efa1b5SStefano Zampini } 2062674ae819SStefano Zampini 2063d71ae5a4SJacob Faibussowitsch PetscErrorCode PCReset_BDDC(PC pc) 2064d71ae5a4SJacob Faibussowitsch { 2065da1bb401SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 20669326c5c6Sstefano_zampini PC_IS *pcis = (PC_IS *)pc->data; 20679326c5c6Sstefano_zampini KSP kspD, kspR, kspC; 2068da1bb401SStefano Zampini 2069da1bb401SStefano Zampini PetscFunctionBegin; 2070674ae819SStefano Zampini /* free BDDC custom data */ 20719566063dSJacob Faibussowitsch PetscCall(PCBDDCResetCustomization(pc)); 2072674ae819SStefano Zampini /* destroy objects related to topography */ 20739566063dSJacob Faibussowitsch PetscCall(PCBDDCResetTopography(pc)); 207434a97f8cSStefano Zampini /* destroy objects for scaling operator */ 20759566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingDestroy(pc)); 2076674ae819SStefano Zampini /* free solvers stuff */ 20779566063dSJacob Faibussowitsch PetscCall(PCBDDCResetSolvers(pc)); 207862a6ff1dSStefano Zampini /* free global vectors needed in presolve */ 20799566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->temp_solution)); 20809566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pcbddc->original_rhs)); 20811dd7afcfSStefano Zampini /* free data created by PCIS */ 20829566063dSJacob Faibussowitsch PetscCall(PCISDestroy(pc)); 20839326c5c6Sstefano_zampini 20849326c5c6Sstefano_zampini /* restore defaults */ 20859326c5c6Sstefano_zampini kspD = pcbddc->ksp_D; 20869326c5c6Sstefano_zampini kspR = pcbddc->ksp_R; 20879326c5c6Sstefano_zampini kspC = pcbddc->coarse_ksp; 20889566063dSJacob Faibussowitsch PetscCall(PetscMemzero(pc->data, sizeof(*pcbddc))); 20899326c5c6Sstefano_zampini pcis->n_neigh = -1; 20909326c5c6Sstefano_zampini pcis->scaling_factor = 1.0; 20919326c5c6Sstefano_zampini pcis->reusesubmatrices = PETSC_TRUE; 20929326c5c6Sstefano_zampini pcbddc->use_local_adj = PETSC_TRUE; 20939326c5c6Sstefano_zampini pcbddc->use_vertices = PETSC_TRUE; 20949326c5c6Sstefano_zampini pcbddc->use_edges = PETSC_TRUE; 20959326c5c6Sstefano_zampini pcbddc->symmetric_primal = PETSC_TRUE; 20969326c5c6Sstefano_zampini pcbddc->vertex_size = 1; 20979326c5c6Sstefano_zampini pcbddc->recompute_topography = PETSC_TRUE; 20989326c5c6Sstefano_zampini pcbddc->coarse_size = -1; 20999326c5c6Sstefano_zampini pcbddc->use_exact_dirichlet_trick = PETSC_TRUE; 21009326c5c6Sstefano_zampini pcbddc->coarsening_ratio = 8; 21019326c5c6Sstefano_zampini pcbddc->coarse_eqs_per_proc = 1; 21029326c5c6Sstefano_zampini pcbddc->benign_compute_correction = PETSC_TRUE; 21039326c5c6Sstefano_zampini pcbddc->nedfield = -1; 21049326c5c6Sstefano_zampini pcbddc->nedglobal = PETSC_TRUE; 21059326c5c6Sstefano_zampini pcbddc->graphmaxcount = PETSC_MAX_INT; 21069326c5c6Sstefano_zampini pcbddc->sub_schurs_layers = -1; 21079326c5c6Sstefano_zampini pcbddc->ksp_D = kspD; 21089326c5c6Sstefano_zampini pcbddc->ksp_R = kspR; 21099326c5c6Sstefano_zampini pcbddc->coarse_ksp = kspC; 21109326c5c6Sstefano_zampini PetscFunctionReturn(0); 21119326c5c6Sstefano_zampini } 21129326c5c6Sstefano_zampini 2113d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDestroy_BDDC(PC pc) 2114d71ae5a4SJacob Faibussowitsch { 21159326c5c6Sstefano_zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 21169326c5c6Sstefano_zampini 21179326c5c6Sstefano_zampini PetscFunctionBegin; 21189566063dSJacob Faibussowitsch PetscCall(PCReset_BDDC(pc)); 21199566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&pcbddc->ksp_D)); 21209566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&pcbddc->ksp_R)); 21219566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&pcbddc->coarse_ksp)); 21229566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDiscreteGradient_C", NULL)); 21239566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDivergenceMat_C", NULL)); 21249566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetChangeOfBasisMat_C", NULL)); 21259566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesLocalIS_C", NULL)); 21269566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesIS_C", NULL)); 212732fe681dSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesLocalIS_C", NULL)); 212832fe681dSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesIS_C", NULL)); 21299566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetCoarseningRatio_C", NULL)); 21309566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevel_C", NULL)); 21319566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetUseExactDirichlet_C", NULL)); 21329566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevels_C", NULL)); 21339566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundaries_C", NULL)); 21349566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundariesLocal_C", NULL)); 21359566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundaries_C", NULL)); 21369566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundariesLocal_C", NULL)); 21379566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundaries_C", NULL)); 21389566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundariesLocal_C", NULL)); 21399566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundaries_C", NULL)); 21409566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundariesLocal_C", NULL)); 21419566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplitting_C", NULL)); 21429566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplittingLocal_C", NULL)); 21439566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", NULL)); 21449566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCCreateFETIDPOperators_C", NULL)); 21459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetRHS_C", NULL)); 21469566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetSolution_C", NULL)); 21479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", NULL)); 21489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", NULL)); 21499566063dSJacob Faibussowitsch PetscCall(PetscFree(pc->data)); 2150da1bb401SStefano Zampini PetscFunctionReturn(0); 2151da1bb401SStefano Zampini } 21521e6b0712SBarry Smith 2153d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetCoordinates_BDDC(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords) 2154d71ae5a4SJacob Faibussowitsch { 2155ab8c8b98SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)pc->data; 2156ab8c8b98SStefano Zampini PCBDDCGraph mat_graph = pcbddc->mat_graph; 2157ab8c8b98SStefano Zampini 2158ab8c8b98SStefano Zampini PetscFunctionBegin; 21599566063dSJacob Faibussowitsch PetscCall(PetscFree(mat_graph->coords)); 21609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nloc * dim, &mat_graph->coords)); 21619566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(mat_graph->coords, coords, nloc * dim)); 2162ab8c8b98SStefano Zampini mat_graph->cnloc = nloc; 2163ab8c8b98SStefano Zampini mat_graph->cdim = dim; 2164ab8c8b98SStefano Zampini mat_graph->cloc = PETSC_FALSE; 21654f819b78SStefano Zampini /* flg setup */ 21664f819b78SStefano Zampini pcbddc->recompute_topography = PETSC_TRUE; 21674f819b78SStefano Zampini pcbddc->corner_selected = PETSC_FALSE; 2168ab8c8b98SStefano Zampini PetscFunctionReturn(0); 2169ab8c8b98SStefano Zampini } 2170ab8c8b98SStefano Zampini 2171d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCPreSolveChangeRHS_BDDC(PC pc, PetscBool *change) 2172d71ae5a4SJacob Faibussowitsch { 2173a06fd7f2SStefano Zampini PetscFunctionBegin; 2174a06fd7f2SStefano Zampini *change = PETSC_TRUE; 2175a06fd7f2SStefano Zampini PetscFunctionReturn(0); 2176a06fd7f2SStefano Zampini } 2177a06fd7f2SStefano Zampini 2178d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) 2179d71ae5a4SJacob Faibussowitsch { 2180674ae819SStefano Zampini FETIDPMat_ctx mat_ctx; 2181266e20e9SStefano Zampini Vec work; 21823425bc38SStefano Zampini PC_IS *pcis; 21833425bc38SStefano Zampini PC_BDDC *pcbddc; 21840c7d97c5SJed Brown 21853425bc38SStefano Zampini PetscFunctionBegin; 21869566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx)); 21873425bc38SStefano Zampini pcis = (PC_IS *)mat_ctx->pc->data; 21883425bc38SStefano Zampini pcbddc = (PC_BDDC *)mat_ctx->pc->data; 21893425bc38SStefano Zampini 21909566063dSJacob Faibussowitsch PetscCall(VecSet(fetidp_flux_rhs, 0.0)); 2191229984c5Sstefano_zampini /* copy rhs since we may change it during PCPreSolve_BDDC */ 219248a46eb9SPierre Jolivet if (!pcbddc->original_rhs) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->original_rhs)); 21936cc1294bSstefano_zampini if (mat_ctx->rhs_flip) { 21949566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(pcbddc->original_rhs, standard_rhs, mat_ctx->rhs_flip)); 21956cc1294bSstefano_zampini } else { 21969566063dSJacob Faibussowitsch PetscCall(VecCopy(standard_rhs, pcbddc->original_rhs)); 21976cc1294bSstefano_zampini } 2198af140850Sstefano_zampini if (mat_ctx->g2g_p) { 2199229984c5Sstefano_zampini /* interface pressure rhs */ 22009566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->g2g_p, fetidp_flux_rhs, pcbddc->original_rhs, INSERT_VALUES, SCATTER_REVERSE)); 22019566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->g2g_p, fetidp_flux_rhs, pcbddc->original_rhs, INSERT_VALUES, SCATTER_REVERSE)); 22029566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->g2g_p, standard_rhs, fetidp_flux_rhs, INSERT_VALUES, SCATTER_FORWARD)); 22039566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->g2g_p, standard_rhs, fetidp_flux_rhs, INSERT_VALUES, SCATTER_FORWARD)); 220448a46eb9SPierre Jolivet if (!mat_ctx->rhs_flip) PetscCall(VecScale(fetidp_flux_rhs, -1.)); 22056cc1294bSstefano_zampini } 2206c08af4c6SStefano Zampini /* 2207c08af4c6SStefano Zampini change of basis for physical rhs if needed 2208c08af4c6SStefano Zampini It also changes the rhs in case of dirichlet boundaries 2209c08af4c6SStefano Zampini */ 22109566063dSJacob Faibussowitsch PetscCall(PCPreSolve_BDDC(mat_ctx->pc, NULL, pcbddc->original_rhs, NULL)); 2211fc17d649SStefano Zampini if (pcbddc->ChangeOfBasisMatrix) { 22129566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, pcbddc->original_rhs, pcbddc->work_change)); 22133738a8e6SStefano Zampini work = pcbddc->work_change; 2214fc17d649SStefano Zampini } else { 22153738a8e6SStefano Zampini work = pcbddc->original_rhs; 2216fc17d649SStefano Zampini } 22173425bc38SStefano Zampini /* store vectors for computation of fetidp final solution */ 22189566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, work, mat_ctx->temp_solution_D, INSERT_VALUES, SCATTER_FORWARD)); 22199566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, work, mat_ctx->temp_solution_D, INSERT_VALUES, SCATTER_FORWARD)); 2220fb223d50SStefano Zampini /* scale rhs since it should be unassembled */ 2221fb223d50SStefano Zampini /* TODO use counter scaling? (also below) */ 22229566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD)); 22239566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD)); 2224674ae819SStefano Zampini /* Apply partition of unity */ 22259566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B, pcis->D, mat_ctx->temp_solution_B)); 22269566063dSJacob Faibussowitsch /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */ 22278eeda7d8SStefano Zampini if (!pcbddc->switch_static) { 22283425bc38SStefano Zampini /* compute partially subassembled Schur complement right-hand side */ 22299566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0)); 22309566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, mat_ctx->temp_solution_D, pcis->vec1_D)); 22319566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0)); 2232c0decd05SBarry Smith /* Cannot propagate up error in KSPSolve() because there is no access to the PC */ 22339566063dSJacob Faibussowitsch PetscCall(MatMult(pcis->A_BI, pcis->vec1_D, pcis->vec1_B)); 22349566063dSJacob Faibussowitsch PetscCall(VecAXPY(mat_ctx->temp_solution_B, -1.0, pcis->vec1_B)); 22359566063dSJacob Faibussowitsch PetscCall(VecSet(work, 0.0)); 22369566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, mat_ctx->temp_solution_B, work, ADD_VALUES, SCATTER_REVERSE)); 22379566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, mat_ctx->temp_solution_B, work, ADD_VALUES, SCATTER_REVERSE)); 22389566063dSJacob Faibussowitsch /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */ 22399566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD)); 22409566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD)); 22419566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B, pcis->D, mat_ctx->temp_solution_B)); 22423425bc38SStefano Zampini } 22433425bc38SStefano Zampini /* BDDC rhs */ 22449566063dSJacob Faibussowitsch PetscCall(VecCopy(mat_ctx->temp_solution_B, pcis->vec1_B)); 22451baa6e33SBarry Smith if (pcbddc->switch_static) PetscCall(VecCopy(mat_ctx->temp_solution_D, pcis->vec1_D)); 22463425bc38SStefano Zampini /* apply BDDC */ 22479566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n)); 22489566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc, PETSC_FALSE)); 22499566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n)); 2250229984c5Sstefano_zampini 22513425bc38SStefano Zampini /* Application of B_delta and assembling of rhs for fetidp fluxes */ 22529566063dSJacob Faibussowitsch PetscCall(MatMult(mat_ctx->B_delta, pcis->vec1_B, mat_ctx->lambda_local)); 22539566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->l2g_lambda, mat_ctx->lambda_local, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD)); 22549566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->l2g_lambda, mat_ctx->lambda_local, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD)); 2255229984c5Sstefano_zampini /* Add contribution to interface pressures */ 2256229984c5Sstefano_zampini if (mat_ctx->l2g_p) { 22579566063dSJacob Faibussowitsch PetscCall(MatMult(mat_ctx->B_BB, pcis->vec1_B, mat_ctx->vP)); 22581baa6e33SBarry Smith if (pcbddc->switch_static) PetscCall(MatMultAdd(mat_ctx->B_BI, pcis->vec1_D, mat_ctx->vP, mat_ctx->vP)); 22599566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->l2g_p, mat_ctx->vP, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD)); 22609566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->l2g_p, mat_ctx->vP, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD)); 2261229984c5Sstefano_zampini } 22623425bc38SStefano Zampini PetscFunctionReturn(0); 22633425bc38SStefano Zampini } 22641e6b0712SBarry Smith 22653425bc38SStefano Zampini /*@ 22660f202f7eSStefano Zampini PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side 22673425bc38SStefano Zampini 22683425bc38SStefano Zampini Collective 22693425bc38SStefano Zampini 22703425bc38SStefano Zampini Input Parameters: 2271f1580f4eSBarry Smith + fetidp_mat - the FETI-DP matrix object obtained by a call to `PCBDDCCreateFETIDPOperators()` 22720f202f7eSStefano Zampini - standard_rhs - the right-hand side of the original linear system 22733425bc38SStefano Zampini 2274f1580f4eSBarry Smith Output Parameter: 22750f202f7eSStefano Zampini . fetidp_flux_rhs - the right-hand side for the FETI-DP linear system 22763425bc38SStefano Zampini 22773425bc38SStefano Zampini Level: developer 22783425bc38SStefano Zampini 227916b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCCreateFETIDPOperators()`, `PCBDDCMatFETIDPGetSolution()` 22803425bc38SStefano Zampini @*/ 2281d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) 2282d71ae5a4SJacob Faibussowitsch { 2283674ae819SStefano Zampini FETIDPMat_ctx mat_ctx; 22843425bc38SStefano Zampini 22853425bc38SStefano Zampini PetscFunctionBegin; 2286266e20e9SStefano Zampini PetscValidHeaderSpecific(fetidp_mat, MAT_CLASSID, 1); 2287266e20e9SStefano Zampini PetscValidHeaderSpecific(standard_rhs, VEC_CLASSID, 2); 2288266e20e9SStefano Zampini PetscValidHeaderSpecific(fetidp_flux_rhs, VEC_CLASSID, 3); 22899566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx)); 2290cac4c232SBarry Smith PetscUseMethod(mat_ctx->pc, "PCBDDCMatFETIDPGetRHS_C", (Mat, Vec, Vec), (fetidp_mat, standard_rhs, fetidp_flux_rhs)); 22913425bc38SStefano Zampini PetscFunctionReturn(0); 22923425bc38SStefano Zampini } 22931e6b0712SBarry Smith 2294d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) 2295d71ae5a4SJacob Faibussowitsch { 2296674ae819SStefano Zampini FETIDPMat_ctx mat_ctx; 22973425bc38SStefano Zampini PC_IS *pcis; 22983425bc38SStefano Zampini PC_BDDC *pcbddc; 2299229984c5Sstefano_zampini Vec work; 23003425bc38SStefano Zampini 23013425bc38SStefano Zampini PetscFunctionBegin; 23029566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx)); 23033425bc38SStefano Zampini pcis = (PC_IS *)mat_ctx->pc->data; 23043425bc38SStefano Zampini pcbddc = (PC_BDDC *)mat_ctx->pc->data; 23053425bc38SStefano Zampini 23063425bc38SStefano Zampini /* apply B_delta^T */ 23079566063dSJacob Faibussowitsch PetscCall(VecSet(pcis->vec1_B, 0.)); 23089566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->l2g_lambda, fetidp_flux_sol, mat_ctx->lambda_local, INSERT_VALUES, SCATTER_REVERSE)); 23099566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->l2g_lambda, fetidp_flux_sol, mat_ctx->lambda_local, INSERT_VALUES, SCATTER_REVERSE)); 23109566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(mat_ctx->B_delta, mat_ctx->lambda_local, pcis->vec1_B)); 2311229984c5Sstefano_zampini if (mat_ctx->l2g_p) { 23129566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->l2g_p, fetidp_flux_sol, mat_ctx->vP, INSERT_VALUES, SCATTER_REVERSE)); 23139566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->l2g_p, fetidp_flux_sol, mat_ctx->vP, INSERT_VALUES, SCATTER_REVERSE)); 23149566063dSJacob Faibussowitsch PetscCall(MatMultAdd(mat_ctx->Bt_BB, mat_ctx->vP, pcis->vec1_B, pcis->vec1_B)); 2315229984c5Sstefano_zampini } 2316229984c5Sstefano_zampini 23173425bc38SStefano Zampini /* compute rhs for BDDC application */ 23189566063dSJacob Faibussowitsch PetscCall(VecAYPX(pcis->vec1_B, -1.0, mat_ctx->temp_solution_B)); 23198eeda7d8SStefano Zampini if (pcbddc->switch_static) { 23209566063dSJacob Faibussowitsch PetscCall(VecCopy(mat_ctx->temp_solution_D, pcis->vec1_D)); 2321229984c5Sstefano_zampini if (mat_ctx->l2g_p) { 23229566063dSJacob Faibussowitsch PetscCall(VecScale(mat_ctx->vP, -1.)); 23239566063dSJacob Faibussowitsch PetscCall(MatMultAdd(mat_ctx->Bt_BI, mat_ctx->vP, pcis->vec1_D, pcis->vec1_D)); 23243425bc38SStefano Zampini } 2325229984c5Sstefano_zampini } 2326229984c5Sstefano_zampini 23273425bc38SStefano Zampini /* apply BDDC */ 23289566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n)); 23299566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc, PETSC_FALSE)); 2330229984c5Sstefano_zampini 2331229984c5Sstefano_zampini /* put values into global vector */ 2332af140850Sstefano_zampini if (pcbddc->ChangeOfBasisMatrix) work = pcbddc->work_change; 2333af140850Sstefano_zampini else work = standard_sol; 23349566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, work, INSERT_VALUES, SCATTER_REVERSE)); 23359566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, work, INSERT_VALUES, SCATTER_REVERSE)); 23368eeda7d8SStefano Zampini if (!pcbddc->switch_static) { 23373425bc38SStefano Zampini /* compute values into the interior if solved for the partially subassembled Schur complement */ 23389566063dSJacob Faibussowitsch PetscCall(MatMult(pcis->A_IB, pcis->vec1_B, pcis->vec1_D)); 23399566063dSJacob Faibussowitsch PetscCall(VecAYPX(pcis->vec1_D, -1.0, mat_ctx->temp_solution_D)); 23409566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0)); 23419566063dSJacob Faibussowitsch PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec1_D)); 23429566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0)); 2343c0decd05SBarry Smith /* Cannot propagate up error in KSPSolve() because there is no access to the PC */ 23443425bc38SStefano Zampini } 2345229984c5Sstefano_zampini 23469566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_D, work, INSERT_VALUES, SCATTER_REVERSE)); 23479566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_D, work, INSERT_VALUES, SCATTER_REVERSE)); 2348266e20e9SStefano Zampini /* add p0 solution to final solution */ 23499566063dSJacob Faibussowitsch PetscCall(PCBDDCBenignGetOrSetP0(mat_ctx->pc, work, PETSC_FALSE)); 23501baa6e33SBarry Smith if (pcbddc->ChangeOfBasisMatrix) PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, work, standard_sol)); 23519566063dSJacob Faibussowitsch PetscCall(PCPostSolve_BDDC(mat_ctx->pc, NULL, NULL, standard_sol)); 2352af140850Sstefano_zampini if (mat_ctx->g2g_p) { 23539566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mat_ctx->g2g_p, fetidp_flux_sol, standard_sol, INSERT_VALUES, SCATTER_REVERSE)); 23549566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mat_ctx->g2g_p, fetidp_flux_sol, standard_sol, INSERT_VALUES, SCATTER_REVERSE)); 2355229984c5Sstefano_zampini } 23563425bc38SStefano Zampini PetscFunctionReturn(0); 23573425bc38SStefano Zampini } 23581e6b0712SBarry Smith 2359d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_BDDCIPC(PC pc, PetscViewer viewer) 2360d71ae5a4SJacob Faibussowitsch { 23615a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 23625a1e936bSStefano Zampini PetscBool isascii; 23635a1e936bSStefano Zampini 23645a1e936bSStefano Zampini PetscFunctionBegin; 23659566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc, &bddcipc_ctx)); 23669566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 236748a46eb9SPierre Jolivet if (isascii) PetscCall(PetscViewerASCIIPrintf(viewer, "BDDC interface preconditioner\n")); 23689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 23699566063dSJacob Faibussowitsch PetscCall(PCView(bddcipc_ctx->bddc, viewer)); 23709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 23715a1e936bSStefano Zampini PetscFunctionReturn(0); 23725a1e936bSStefano Zampini } 23735a1e936bSStefano Zampini 2374d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetUp_BDDCIPC(PC pc) 2375d71ae5a4SJacob Faibussowitsch { 23765a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 23775a1e936bSStefano Zampini PetscBool isbddc; 23785a1e936bSStefano Zampini Vec vv; 23795a1e936bSStefano Zampini IS is; 23805a1e936bSStefano Zampini PC_IS *pcis; 23815a1e936bSStefano Zampini 23825a1e936bSStefano Zampini PetscFunctionBegin; 23839566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc, &bddcipc_ctx)); 23849566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)bddcipc_ctx->bddc, PCBDDC, &isbddc)); 238528b400f6SJacob Faibussowitsch PetscCheck(isbddc, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Invalid type %s. Must be of type bddc", ((PetscObject)bddcipc_ctx->bddc)->type_name); 23869566063dSJacob Faibussowitsch PetscCall(PCSetUp(bddcipc_ctx->bddc)); 23875a1e936bSStefano Zampini 23885a1e936bSStefano Zampini /* create interface scatter */ 23895a1e936bSStefano Zampini pcis = (PC_IS *)(bddcipc_ctx->bddc->data); 23909566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l)); 23919566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(pc->pmat, &vv, NULL)); 23929566063dSJacob Faibussowitsch PetscCall(ISRenumber(pcis->is_B_global, NULL, NULL, &is)); 23939566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(vv, is, pcis->vec1_B, NULL, &bddcipc_ctx->g2l)); 23949566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 23959566063dSJacob Faibussowitsch PetscCall(VecDestroy(&vv)); 23965a1e936bSStefano Zampini PetscFunctionReturn(0); 23975a1e936bSStefano Zampini } 23985a1e936bSStefano Zampini 2399d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_BDDCIPC(PC pc, Vec r, Vec x) 2400d71ae5a4SJacob Faibussowitsch { 24015a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 24025a1e936bSStefano Zampini PC_IS *pcis; 24035a1e936bSStefano Zampini VecScatter tmps; 24045a1e936bSStefano Zampini 24055a1e936bSStefano Zampini PetscFunctionBegin; 24069566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc, &bddcipc_ctx)); 24075a1e936bSStefano Zampini pcis = (PC_IS *)(bddcipc_ctx->bddc->data); 24085a1e936bSStefano Zampini tmps = pcis->global_to_B; 24095a1e936bSStefano Zampini pcis->global_to_B = bddcipc_ctx->g2l; 24109566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc, r, pcis->vec1_B)); 24119566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc, PETSC_FALSE)); 24129566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc, pcis->vec1_B, x)); 24135a1e936bSStefano Zampini pcis->global_to_B = tmps; 24145a1e936bSStefano Zampini PetscFunctionReturn(0); 24155a1e936bSStefano Zampini } 24165a1e936bSStefano Zampini 2417d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_BDDCIPC(PC pc, Vec r, Vec x) 2418d71ae5a4SJacob Faibussowitsch { 24195a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 24205a1e936bSStefano Zampini PC_IS *pcis; 24215a1e936bSStefano Zampini VecScatter tmps; 24225a1e936bSStefano Zampini 24235a1e936bSStefano Zampini PetscFunctionBegin; 24249566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc, &bddcipc_ctx)); 24255a1e936bSStefano Zampini pcis = (PC_IS *)(bddcipc_ctx->bddc->data); 24265a1e936bSStefano Zampini tmps = pcis->global_to_B; 24275a1e936bSStefano Zampini pcis->global_to_B = bddcipc_ctx->g2l; 24289566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc, r, pcis->vec1_B)); 24299566063dSJacob Faibussowitsch PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc, PETSC_TRUE)); 24309566063dSJacob Faibussowitsch PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc, pcis->vec1_B, x)); 24315a1e936bSStefano Zampini pcis->global_to_B = tmps; 24325a1e936bSStefano Zampini PetscFunctionReturn(0); 24335a1e936bSStefano Zampini } 24345a1e936bSStefano Zampini 2435d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_BDDCIPC(PC pc) 2436d71ae5a4SJacob Faibussowitsch { 24375a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 24385a1e936bSStefano Zampini 24395a1e936bSStefano Zampini PetscFunctionBegin; 24409566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(pc, &bddcipc_ctx)); 24419566063dSJacob Faibussowitsch PetscCall(PCDestroy(&bddcipc_ctx->bddc)); 24429566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l)); 24439566063dSJacob Faibussowitsch PetscCall(PetscFree(bddcipc_ctx)); 24445a1e936bSStefano Zampini PetscFunctionReturn(0); 24455a1e936bSStefano Zampini } 24465a1e936bSStefano Zampini 24473425bc38SStefano Zampini /*@ 24480f202f7eSStefano Zampini PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system 24493425bc38SStefano Zampini 24503425bc38SStefano Zampini Collective 24513425bc38SStefano Zampini 24523425bc38SStefano Zampini Input Parameters: 2453f1580f4eSBarry Smith + fetidp_mat - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators()` 2454f1580f4eSBarry Smith - fetidp_flux_sol - the solution of the FETI-DP linear system` 24553425bc38SStefano Zampini 2456f1580f4eSBarry Smith Output Parameter: 24570f202f7eSStefano Zampini . standard_sol - the solution defined on the physical domain 24583425bc38SStefano Zampini 24593425bc38SStefano Zampini Level: developer 24603425bc38SStefano Zampini 246116b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCCreateFETIDPOperators()`, `PCBDDCMatFETIDPGetRHS()` 24623425bc38SStefano Zampini @*/ 2463d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) 2464d71ae5a4SJacob Faibussowitsch { 2465674ae819SStefano Zampini FETIDPMat_ctx mat_ctx; 24663425bc38SStefano Zampini 24673425bc38SStefano Zampini PetscFunctionBegin; 2468266e20e9SStefano Zampini PetscValidHeaderSpecific(fetidp_mat, MAT_CLASSID, 1); 2469266e20e9SStefano Zampini PetscValidHeaderSpecific(fetidp_flux_sol, VEC_CLASSID, 2); 2470266e20e9SStefano Zampini PetscValidHeaderSpecific(standard_sol, VEC_CLASSID, 3); 24719566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx)); 2472cac4c232SBarry Smith PetscUseMethod(mat_ctx->pc, "PCBDDCMatFETIDPGetSolution_C", (Mat, Vec, Vec), (fetidp_mat, fetidp_flux_sol, standard_sol)); 24733425bc38SStefano Zampini PetscFunctionReturn(0); 24743425bc38SStefano Zampini } 24751e6b0712SBarry Smith 2476d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc) 2477d71ae5a4SJacob Faibussowitsch { 2478674ae819SStefano Zampini FETIDPMat_ctx fetidpmat_ctx; 24793425bc38SStefano Zampini Mat newmat; 2480674ae819SStefano Zampini FETIDPPC_ctx fetidppc_ctx; 24813425bc38SStefano Zampini PC newpc; 2482ce94432eSBarry Smith MPI_Comm comm; 24833425bc38SStefano Zampini 24843425bc38SStefano Zampini PetscFunctionBegin; 24859566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)pc, &comm)); 248615579a77SStefano Zampini /* FETI-DP matrix */ 24879566063dSJacob Faibussowitsch PetscCall(PCBDDCCreateFETIDPMatContext(pc, &fetidpmat_ctx)); 24881720468bSStefano Zampini fetidpmat_ctx->fully_redundant = fully_redundant; 24899566063dSJacob Faibussowitsch PetscCall(PCBDDCSetupFETIDPMatContext(fetidpmat_ctx)); 24909566063dSJacob Faibussowitsch PetscCall(MatCreateShell(comm, fetidpmat_ctx->n, fetidpmat_ctx->n, fetidpmat_ctx->N, fetidpmat_ctx->N, fetidpmat_ctx, &newmat)); 24919566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)newmat, !fetidpmat_ctx->l2g_lambda_only ? "F" : "G")); 24929566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(newmat, MATOP_MULT, (void (*)(void))FETIDPMatMult)); 24939566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(newmat, MATOP_MULT_TRANSPOSE, (void (*)(void))FETIDPMatMultTranspose)); 24949566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(newmat, MATOP_DESTROY, (void (*)(void))PCBDDCDestroyFETIDPMat)); 249515579a77SStefano Zampini /* propagate MatOptions */ 249615579a77SStefano Zampini { 249715579a77SStefano Zampini PC_BDDC *pcbddc = (PC_BDDC *)fetidpmat_ctx->pc->data; 2498b94d7dedSBarry Smith PetscBool isset, issym; 249915579a77SStefano Zampini 2500b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(pc->mat, &isset, &issym)); 2501b94d7dedSBarry Smith if ((isset && issym) || pcbddc->symmetric_primal) PetscCall(MatSetOption(newmat, MAT_SYMMETRIC, PETSC_TRUE)); 250215579a77SStefano Zampini } 25039566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(newmat, prefix)); 25049566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(newmat, "fetidp_")); 25059566063dSJacob Faibussowitsch PetscCall(MatSetUp(newmat)); 250615579a77SStefano Zampini /* FETI-DP preconditioner */ 25079566063dSJacob Faibussowitsch PetscCall(PCBDDCCreateFETIDPPCContext(pc, &fetidppc_ctx)); 25089566063dSJacob Faibussowitsch PetscCall(PCBDDCSetupFETIDPPCContext(newmat, fetidppc_ctx)); 25099566063dSJacob Faibussowitsch PetscCall(PCCreate(comm, &newpc)); 25109566063dSJacob Faibussowitsch PetscCall(PCSetOperators(newpc, newmat, newmat)); 25119566063dSJacob Faibussowitsch PetscCall(PCSetOptionsPrefix(newpc, prefix)); 25129566063dSJacob Faibussowitsch PetscCall(PCAppendOptionsPrefix(newpc, "fetidp_")); 25139566063dSJacob Faibussowitsch PetscCall(PCSetErrorIfFailure(newpc, pc->erroriffailure)); 251415579a77SStefano Zampini if (!fetidpmat_ctx->l2g_lambda_only) { /* standard FETI-DP */ 25159566063dSJacob Faibussowitsch PetscCall(PCSetType(newpc, PCSHELL)); 25169566063dSJacob Faibussowitsch PetscCall(PCShellSetName(newpc, "FETI-DP multipliers")); 25179566063dSJacob Faibussowitsch PetscCall(PCShellSetContext(newpc, fetidppc_ctx)); 25189566063dSJacob Faibussowitsch PetscCall(PCShellSetApply(newpc, FETIDPPCApply)); 25199566063dSJacob Faibussowitsch PetscCall(PCShellSetApplyTranspose(newpc, FETIDPPCApplyTranspose)); 25209566063dSJacob Faibussowitsch PetscCall(PCShellSetView(newpc, FETIDPPCView)); 25219566063dSJacob Faibussowitsch PetscCall(PCShellSetDestroy(newpc, PCBDDCDestroyFETIDPPC)); 25225a1e936bSStefano Zampini } else { /* saddle-point FETI-DP */ 25235a1e936bSStefano Zampini Mat M; 25245a1e936bSStefano Zampini PetscInt psize; 25255a1e936bSStefano Zampini PetscBool fake = PETSC_FALSE, isfieldsplit; 2526e1214c54Sstefano_zampini 25279566063dSJacob Faibussowitsch PetscCall(ISViewFromOptions(fetidpmat_ctx->lagrange, NULL, "-lag_view")); 25289566063dSJacob Faibussowitsch PetscCall(ISViewFromOptions(fetidpmat_ctx->pressure, NULL, "-press_view")); 25299566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_PPmat", (PetscObject *)&M)); 25309566063dSJacob Faibussowitsch PetscCall(PCSetType(newpc, PCFIELDSPLIT)); 25319566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetIS(newpc, "lag", fetidpmat_ctx->lagrange)); 25329566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetIS(newpc, "p", fetidpmat_ctx->pressure)); 25339566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetType(newpc, PC_COMPOSITE_SCHUR)); 25349566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetSchurFactType(newpc, PC_FIELDSPLIT_SCHUR_FACT_DIAG)); 25359566063dSJacob Faibussowitsch PetscCall(ISGetSize(fetidpmat_ctx->pressure, &psize)); 25365a1e936bSStefano Zampini if (psize != M->rmap->N) { 25375a1e936bSStefano Zampini Mat M2; 25385a1e936bSStefano Zampini PetscInt lpsize; 25395a1e936bSStefano Zampini 25405a1e936bSStefano Zampini fake = PETSC_TRUE; 25419566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(fetidpmat_ctx->pressure, &lpsize)); 25429566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &M2)); 25439566063dSJacob Faibussowitsch PetscCall(MatSetType(M2, MATAIJ)); 25449566063dSJacob Faibussowitsch PetscCall(MatSetSizes(M2, lpsize, lpsize, psize, psize)); 25459566063dSJacob Faibussowitsch PetscCall(MatSetUp(M2)); 25469566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(M2, MAT_FINAL_ASSEMBLY)); 25479566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(M2, MAT_FINAL_ASSEMBLY)); 25489566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetSchurPre(newpc, PC_FIELDSPLIT_SCHUR_PRE_USER, M2)); 25499566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M2)); 25505a1e936bSStefano Zampini } else { 25519566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetSchurPre(newpc, PC_FIELDSPLIT_SCHUR_PRE_USER, M)); 25525a1e936bSStefano Zampini } 25539566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSetSchurScale(newpc, 1.0)); 255415579a77SStefano Zampini 255515579a77SStefano Zampini /* we need to setfromoptions and setup here to access the blocks */ 25569566063dSJacob Faibussowitsch PetscCall(PCSetFromOptions(newpc)); 25579566063dSJacob Faibussowitsch PetscCall(PCSetUp(newpc)); 2558e1214c54Sstefano_zampini 25595a1e936bSStefano Zampini /* user may have changed the type (e.g. -fetidp_pc_type none) */ 25609566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)newpc, PCFIELDSPLIT, &isfieldsplit)); 25615a1e936bSStefano Zampini if (isfieldsplit) { 25625a1e936bSStefano Zampini KSP *ksps; 25635a1e936bSStefano Zampini PC ppc, lagpc; 25645a1e936bSStefano Zampini PetscInt nn; 2565064a4176SStefano Zampini PetscBool ismatis, matisok = PETSC_FALSE, check = PETSC_FALSE; 25665a1e936bSStefano Zampini 2567e1214c54Sstefano_zampini /* set the solver for the (0,0) block */ 25689566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSchurGetSubKSP(newpc, &nn, &ksps)); 25695a1e936bSStefano Zampini if (!nn) { /* not of type PC_COMPOSITE_SCHUR */ 25709566063dSJacob Faibussowitsch PetscCall(PCFieldSplitGetSubKSP(newpc, &nn, &ksps)); 25715a1e936bSStefano Zampini if (!fake) { /* pass pmat to the pressure solver */ 25725a1e936bSStefano Zampini Mat F; 25735a1e936bSStefano Zampini 25749566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(ksps[1], &F, NULL)); 25759566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(ksps[1], F, M)); 25765a1e936bSStefano Zampini } 25775a1e936bSStefano Zampini } else { 2578b94d7dedSBarry Smith PetscBool issym, isset; 25795a1e936bSStefano Zampini Mat S; 25805a1e936bSStefano Zampini 25819566063dSJacob Faibussowitsch PetscCall(PCFieldSplitSchurGetS(newpc, &S)); 2582b94d7dedSBarry Smith PetscCall(MatIsSymmetricKnown(newmat, &isset, &issym)); 2583b94d7dedSBarry Smith if (isset) PetscCall(MatSetOption(S, MAT_SYMMETRIC, issym)); 25845a1e936bSStefano Zampini } 25859566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksps[0], &lagpc)); 25869566063dSJacob Faibussowitsch PetscCall(PCSetType(lagpc, PCSHELL)); 25879566063dSJacob Faibussowitsch PetscCall(PCShellSetName(lagpc, "FETI-DP multipliers")); 25889566063dSJacob Faibussowitsch PetscCall(PCShellSetContext(lagpc, fetidppc_ctx)); 25899566063dSJacob Faibussowitsch PetscCall(PCShellSetApply(lagpc, FETIDPPCApply)); 25909566063dSJacob Faibussowitsch PetscCall(PCShellSetApplyTranspose(lagpc, FETIDPPCApplyTranspose)); 25919566063dSJacob Faibussowitsch PetscCall(PCShellSetView(lagpc, FETIDPPCView)); 25929566063dSJacob Faibussowitsch PetscCall(PCShellSetDestroy(lagpc, PCBDDCDestroyFETIDPPC)); 25935a1e936bSStefano Zampini 25945a1e936bSStefano Zampini /* Olof's idea: interface Schur complement preconditioner for the mass matrix */ 25959566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksps[1], &ppc)); 25965a1e936bSStefano Zampini if (fake) { 25975a1e936bSStefano Zampini BDDCIPC_ctx bddcipc_ctx; 2598ff11fd76SStefano Zampini PetscContainer c; 25995a1e936bSStefano Zampini 26005a1e936bSStefano Zampini matisok = PETSC_TRUE; 26015a1e936bSStefano Zampini 26025a1e936bSStefano Zampini /* create inner BDDC solver */ 26039566063dSJacob Faibussowitsch PetscCall(PetscNew(&bddcipc_ctx)); 26049566063dSJacob Faibussowitsch PetscCall(PCCreate(comm, &bddcipc_ctx->bddc)); 26059566063dSJacob Faibussowitsch PetscCall(PCSetType(bddcipc_ctx->bddc, PCBDDC)); 26069566063dSJacob Faibussowitsch PetscCall(PCSetOperators(bddcipc_ctx->bddc, M, M)); 26079566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_pCSR", (PetscObject *)&c)); 26089566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)M, MATIS, &ismatis)); 2609ff11fd76SStefano Zampini if (c && ismatis) { 2610ff11fd76SStefano Zampini Mat lM; 2611ff11fd76SStefano Zampini PetscInt *csr, n; 2612ff11fd76SStefano Zampini 26139566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(M, &lM)); 26149566063dSJacob Faibussowitsch PetscCall(MatGetSize(lM, &n, NULL)); 26159566063dSJacob Faibussowitsch PetscCall(PetscContainerGetPointer(c, (void **)&csr)); 26169566063dSJacob Faibussowitsch PetscCall(PCBDDCSetLocalAdjacencyGraph(bddcipc_ctx->bddc, n, csr, csr + (n + 1), PETSC_COPY_VALUES)); 26179566063dSJacob Faibussowitsch PetscCall(MatISRestoreLocalMat(M, &lM)); 2618ff11fd76SStefano Zampini } 26199566063dSJacob Faibussowitsch PetscCall(PCSetOptionsPrefix(bddcipc_ctx->bddc, ((PetscObject)ksps[1])->prefix)); 26209566063dSJacob Faibussowitsch PetscCall(PCSetErrorIfFailure(bddcipc_ctx->bddc, pc->erroriffailure)); 26219566063dSJacob Faibussowitsch PetscCall(PCSetFromOptions(bddcipc_ctx->bddc)); 26225a1e936bSStefano Zampini 26235a1e936bSStefano Zampini /* wrap the interface application */ 26249566063dSJacob Faibussowitsch PetscCall(PCSetType(ppc, PCSHELL)); 26259566063dSJacob Faibussowitsch PetscCall(PCShellSetName(ppc, "FETI-DP pressure")); 26269566063dSJacob Faibussowitsch PetscCall(PCShellSetContext(ppc, bddcipc_ctx)); 26279566063dSJacob Faibussowitsch PetscCall(PCShellSetSetUp(ppc, PCSetUp_BDDCIPC)); 26289566063dSJacob Faibussowitsch PetscCall(PCShellSetApply(ppc, PCApply_BDDCIPC)); 26299566063dSJacob Faibussowitsch PetscCall(PCShellSetApplyTranspose(ppc, PCApplyTranspose_BDDCIPC)); 26309566063dSJacob Faibussowitsch PetscCall(PCShellSetView(ppc, PCView_BDDCIPC)); 26319566063dSJacob Faibussowitsch PetscCall(PCShellSetDestroy(ppc, PCDestroy_BDDCIPC)); 26325a1e936bSStefano Zampini } 26335a1e936bSStefano Zampini 26345a1e936bSStefano Zampini /* determine if we need to assemble M to construct a preconditioner */ 26355a1e936bSStefano Zampini if (!matisok) { 26369566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)M, MATIS, &ismatis)); 26379566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)ppc, &matisok, PCBDDC, PCJACOBI, PCNONE, PCMG, "")); 263848a46eb9SPierre Jolivet if (ismatis && !matisok) PetscCall(MatConvert(M, MATAIJ, MAT_INPLACE_MATRIX, &M)); 26395a1e936bSStefano Zampini } 2640064a4176SStefano Zampini 2641064a4176SStefano Zampini /* run the subproblems to check convergence */ 26429566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)newmat)->prefix, "-check_saddlepoint", &check, NULL)); 2643064a4176SStefano Zampini if (check) { 2644064a4176SStefano Zampini PetscInt i; 2645064a4176SStefano Zampini 2646064a4176SStefano Zampini for (i = 0; i < nn; i++) { 2647064a4176SStefano Zampini KSP kspC; 2648064a4176SStefano Zampini PC pc; 2649064a4176SStefano Zampini Mat F, pF; 2650064a4176SStefano Zampini Vec x, y; 2651064a4176SStefano Zampini PetscBool isschur, prec = PETSC_TRUE; 2652064a4176SStefano Zampini 26539566063dSJacob Faibussowitsch PetscCall(KSPCreate(PetscObjectComm((PetscObject)ksps[i]), &kspC)); 26549566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(kspC, ((PetscObject)ksps[i])->prefix)); 26559566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(kspC, "check_")); 26569566063dSJacob Faibussowitsch PetscCall(KSPGetOperators(ksps[i], &F, &pF)); 26579566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)F, MATSCHURCOMPLEMENT, &isschur)); 2658064a4176SStefano Zampini if (isschur) { 2659064a4176SStefano Zampini KSP kspS, kspS2; 2660064a4176SStefano Zampini Mat A00, pA00, A10, A01, A11; 2661064a4176SStefano Zampini char prefix[256]; 2662064a4176SStefano Zampini 26639566063dSJacob Faibussowitsch PetscCall(MatSchurComplementGetKSP(F, &kspS)); 26649566063dSJacob Faibussowitsch PetscCall(MatSchurComplementGetSubMatrices(F, &A00, &pA00, &A01, &A10, &A11)); 26659566063dSJacob Faibussowitsch PetscCall(MatCreateSchurComplement(A00, pA00, A01, A10, A11, &F)); 26669566063dSJacob Faibussowitsch PetscCall(MatSchurComplementGetKSP(F, &kspS2)); 26679566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(prefix, sizeof(prefix), "%sschur_", ((PetscObject)kspC)->prefix)); 26689566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(kspS2, prefix)); 26699566063dSJacob Faibussowitsch PetscCall(KSPGetPC(kspS2, &pc)); 26709566063dSJacob Faibussowitsch PetscCall(PCSetType(pc, PCKSP)); 26719566063dSJacob Faibussowitsch PetscCall(PCKSPSetKSP(pc, kspS)); 26729566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(kspS2)); 26739566063dSJacob Faibussowitsch PetscCall(KSPGetPC(kspS2, &pc)); 26749566063dSJacob Faibussowitsch PetscCall(PCSetUseAmat(pc, PETSC_TRUE)); 2675064a4176SStefano Zampini } else { 26769566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)F)); 2677064a4176SStefano Zampini } 26789566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(kspC)); 26799566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)kspC)->prefix, "-preconditioned", &prec, NULL)); 2680064a4176SStefano Zampini if (prec) { 26819566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksps[i], &pc)); 26829566063dSJacob Faibussowitsch PetscCall(KSPSetPC(kspC, pc)); 2683064a4176SStefano Zampini } 26849566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(kspC, F, pF)); 26859566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(F, &x, &y)); 26869566063dSJacob Faibussowitsch PetscCall(VecSetRandom(x, NULL)); 26879566063dSJacob Faibussowitsch PetscCall(MatMult(F, x, y)); 26889566063dSJacob Faibussowitsch PetscCall(KSPSolve(kspC, y, x)); 26899566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(kspC, pc, x)); 26909566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&kspC)); 26919566063dSJacob Faibussowitsch PetscCall(MatDestroy(&F)); 26929566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 26939566063dSJacob Faibussowitsch PetscCall(VecDestroy(&y)); 2694064a4176SStefano Zampini } 2695064a4176SStefano Zampini } 26969566063dSJacob Faibussowitsch PetscCall(PetscFree(ksps)); 2697e1214c54Sstefano_zampini } 26985a1e936bSStefano Zampini } 26993425bc38SStefano Zampini /* return pointers for objects created */ 27003425bc38SStefano Zampini *fetidp_mat = newmat; 27013425bc38SStefano Zampini *fetidp_pc = newpc; 27023425bc38SStefano Zampini PetscFunctionReturn(0); 27033425bc38SStefano Zampini } 27041e6b0712SBarry Smith 270594ef8ddeSSatish Balay /*@C 27060f202f7eSStefano Zampini PCBDDCCreateFETIDPOperators - Create FETI-DP operators 27073425bc38SStefano Zampini 27083425bc38SStefano Zampini Collective 27093425bc38SStefano Zampini 27103425bc38SStefano Zampini Input Parameters: 27111720468bSStefano Zampini + pc - the BDDC preconditioning context (setup should have been called before) 2712547c9a8eSstefano_zampini . fully_redundant - true for a fully redundant set of Lagrange multipliers 2713547c9a8eSstefano_zampini - prefix - optional options database prefix for the objects to be created (can be NULL) 271428509bceSStefano Zampini 271528509bceSStefano Zampini Output Parameters: 27160f202f7eSStefano Zampini + fetidp_mat - shell FETI-DP matrix object 27170f202f7eSStefano Zampini - fetidp_pc - shell Dirichlet preconditioner for FETI-DP matrix 271828509bceSStefano Zampini 27193425bc38SStefano Zampini Level: developer 27203425bc38SStefano Zampini 2721f1580f4eSBarry Smith Note: 2722f1580f4eSBarry Smith Currently the only operations provided for FETI-DP matrix are `MatMult()` and `MatMultTranspose()` 27233425bc38SStefano Zampini 272416b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCMatFETIDPGetRHS()`, `PCBDDCMatFETIDPGetSolution()` 27253425bc38SStefano Zampini @*/ 2726d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc) 2727d71ae5a4SJacob Faibussowitsch { 27283425bc38SStefano Zampini PetscFunctionBegin; 27293425bc38SStefano Zampini PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 27303425bc38SStefano Zampini if (pc->setupcalled) { 2731cac4c232SBarry Smith PetscUseMethod(pc, "PCBDDCCreateFETIDPOperators_C", (PC, PetscBool, const char *, Mat *, PC *), (pc, fully_redundant, prefix, fetidp_mat, fetidp_pc)); 27326080607fSStefano Zampini } else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "You must call PCSetup_BDDC() first"); 27333425bc38SStefano Zampini PetscFunctionReturn(0); 27343425bc38SStefano Zampini } 2735f1580f4eSBarry Smith 2736da1bb401SStefano Zampini /*MC 2737f1580f4eSBarry Smith PCBDDC - Balancing Domain Decomposition by Constraints preconditioners 27380c7d97c5SJed Brown 2739f1580f4eSBarry Smith Requires `MATIS` matrices (Pmat) with local matrices (inside the `MATIS`) of type `MATSEQAIJ`, `MATSEQBAIJ` or `MATSEQSBAIJ` 274028509bceSStefano Zampini 274128509bceSStefano Zampini It also works with unsymmetric and indefinite problems. 274228509bceSStefano Zampini 2743f1580f4eSBarry Smith Unlike 'conventional' interface preconditioners, `PCBDDC` iterates over all degrees of freedom, not just those on the interface. This allows the use 2744f1580f4eSBarry Smith of approximate solvers on the subdomains. 2745b6fdb6dfSStefano Zampini 2746f1580f4eSBarry Smith Approximate local solvers are automatically adapted (see [1]) if the user has attached a nullspace object to the subdomain matrices, and informed 2747f1580f4eSBarry Smith `PCBDDC` of using approximate solvers (via the command line). 274828509bceSStefano Zampini 2749f1580f4eSBarry Smith 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. 2750f1580f4eSBarry Smith The latter can be customized by using `PCBDDCSetLocalAdjacencyGraph()` 275128509bceSStefano Zampini 2752f1580f4eSBarry Smith Additional information on dofs can be provided by using `PCBDDCSetDofsSplitting()`, `PCBDDCSetDirichletBoundaries()`, `PCBDDCSetNeumannBoundaries()`, and 2753f1580f4eSBarry Smith `PCBDDCSetPrimalVerticesIS()` and their local counterparts. 275428509bceSStefano Zampini 2755f1580f4eSBarry Smith Constraints can be customized by attaching a `MatNullSpace` object to the `MATIS` matrix via `MatSetNearNullSpace()`. Non-singular modes are retained via SVD. 275628509bceSStefano Zampini 2757f1580f4eSBarry Smith Change of basis is performed similarly to [2] when requested. When more than one constraint is present on a single connected component 2758f1580f4eSBarry Smith (i.e. an edge or a face), a robust method based on local QR factorizations is used. 2759f1580f4eSBarry Smith User defined change of basis can be passed to `PCBDDC` with `PCBDDCSetChangeOfBasisMat()` 276028509bceSStefano Zampini 2761f1580f4eSBarry Smith The PETSc implementation also supports multilevel `PCBDDC` [3]. Coarse grids are partitioned using a `MatPartitioning` object. 276228509bceSStefano Zampini 2763f1580f4eSBarry Smith Adaptive selection of primal constraints [4] is supported for SPD systems with high-contrast in the coefficients if MUMPS or MKL_PARDISO are present. 2764f1580f4eSBarry Smith Future versions of the code will also consider using PASTIX. 27650f202f7eSStefano Zampini 2766f1580f4eSBarry Smith An experimental interface to the FETI-DP method is available. FETI-DP operators could be created using `PCBDDCCreateFETIDPOperators()`. 2767f1580f4eSBarry Smith A stand-alone class for the FETI-DP method will be provided in the next releases. 27680f202f7eSStefano Zampini 2769f1580f4eSBarry Smith Options Database Keys: 2770a2b725a8SWilliam Gropp + -pc_bddc_use_vertices <true> - use or not vertices in primal space 27710f202f7eSStefano Zampini . -pc_bddc_use_edges <true> - use or not edges in primal space 27720f202f7eSStefano Zampini . -pc_bddc_use_faces <false> - use or not faces in primal space 27730f202f7eSStefano Zampini . -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems 27740f202f7eSStefano Zampini . -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only) 27750f202f7eSStefano Zampini . -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested 27760f202f7eSStefano Zampini . -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1]) 277728509bceSStefano Zampini . -pc_bddc_levels <0> - maximum number of levels for multilevel 27780f202f7eSStefano Zampini . -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) 27795459c157SBarry Smith . -pc_bddc_coarse_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) 27800f202f7eSStefano Zampini . -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling 278171f2caa7Sprj- . -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) 2782bd2a564bSStefano Zampini . -pc_bddc_adaptive_threshold <0.0> - when a value different than zero is specified, adaptive selection of constraints is performed on edges and faces (requires deluxe scaling and MUMPS or MKL_PARDISO installed) 278328509bceSStefano Zampini - -pc_bddc_check_level <0> - set verbosity level of debugging output 278428509bceSStefano Zampini 2785f1580f4eSBarry Smith Options for Dirichlet, Neumann or coarse solver can be set using the appropriate options prefix 278628509bceSStefano Zampini .vb 278728509bceSStefano Zampini -pc_bddc_dirichlet_ 278828509bceSStefano Zampini -pc_bddc_neumann_ 278928509bceSStefano Zampini -pc_bddc_coarse_ 279028509bceSStefano Zampini .ve 2791f1580f4eSBarry Smith e.g. -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. `PCBDDC` uses by default `KSPPREONLY` and `PCLU`. 279228509bceSStefano Zampini 2793f1580f4eSBarry Smith When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified using the options prefix 279428509bceSStefano Zampini .vb 2795312be037SStefano Zampini -pc_bddc_dirichlet_lN_ 2796312be037SStefano Zampini -pc_bddc_neumann_lN_ 2797312be037SStefano Zampini -pc_bddc_coarse_lN_ 279828509bceSStefano Zampini .ve 27990f202f7eSStefano Zampini Note that level number ranges from the finest (0) to the coarsest (N). 2800f1580f4eSBarry Smith In order to specify options for the `PCBDDC` operators at the coarser levels (and not for the solvers), prepend -pc_bddc_coarse_ or -pc_bddc_coarse_l 2801f1580f4eSBarry Smith to the option, e.g. 28020f202f7eSStefano Zampini .vb 28030f202f7eSStefano Zampini -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3 28040f202f7eSStefano Zampini .ve 28050f202f7eSStefano Zampini 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 2806da1bb401SStefano Zampini 2807be4a8d98Sprj- References: 2808606c0280SSatish Balay + * - C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149--168, March 2007 2809606c0280SSatish Balay . * - A. Klawonn and O. B. Widlund. "Dual-Primal FETI Methods for Linear Elasticity", Communications on Pure and Applied Mathematics Volume 59, Issue 11, pages 1523--1572, November 2006 2810606c0280SSatish Balay . * - J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", Computing Volume 83, Issue 2--3, pages 55--85, November 2008 2811606c0280SSatish Balay - * - 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 2812be4a8d98Sprj- 2813da1bb401SStefano Zampini Level: intermediate 2814da1bb401SStefano Zampini 2815da1bb401SStefano Zampini Contributed by Stefano Zampini 2816da1bb401SStefano Zampini 2817f1580f4eSBarry Smith .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `MATIS`, `PCLU`, `PGGAMG`, `PC`, `PCBDDCSetLocalAdjacencyGraph()`, `PCBDDCSetDofsSplitting()`, 2818f1580f4eSBarry Smith `PCBDDCSetDirichletBoundaries()`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCSetPrimalVerticesIS()`, `MatNullSpace`, `MatSetNearNullSpace()`, 2819f1580f4eSBarry Smith `PCBDDCSetChangeOfBasisMat()`, `PCBDDCCreateFETIDPOperators()`, `PCNN` 2820da1bb401SStefano Zampini M*/ 2821b2573a8aSBarry Smith 2822d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc) 2823d71ae5a4SJacob Faibussowitsch { 2824da1bb401SStefano Zampini PC_BDDC *pcbddc; 2825da1bb401SStefano Zampini 2826da1bb401SStefano Zampini PetscFunctionBegin; 28274dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&pcbddc)); 28283ec1f749SStefano Zampini pc->data = pcbddc; 2829da1bb401SStefano Zampini 2830da1bb401SStefano Zampini /* create PCIS data structure */ 28319566063dSJacob Faibussowitsch PetscCall(PCISCreate(pc)); 2832da1bb401SStefano Zampini 28339326c5c6Sstefano_zampini /* create local graph structure */ 28349566063dSJacob Faibussowitsch PetscCall(PCBDDCGraphCreate(&pcbddc->mat_graph)); 28359326c5c6Sstefano_zampini 28369326c5c6Sstefano_zampini /* BDDC nonzero defaults */ 28376d9e27e4SStefano Zampini pcbddc->use_nnsp = PETSC_TRUE; 283808a5cf49SStefano Zampini pcbddc->use_local_adj = PETSC_TRUE; 283947d04d0dSStefano Zampini pcbddc->use_vertices = PETSC_TRUE; 284047d04d0dSStefano Zampini pcbddc->use_edges = PETSC_TRUE; 28413301b35fSStefano Zampini pcbddc->symmetric_primal = PETSC_TRUE; 284214f95afaSStefano Zampini pcbddc->vertex_size = 1; 2843c703fcc7SStefano Zampini pcbddc->recompute_topography = PETSC_TRUE; 284468457ee5SStefano Zampini pcbddc->coarse_size = -1; 284585c4d303SStefano Zampini pcbddc->use_exact_dirichlet_trick = PETSC_TRUE; 284647d04d0dSStefano Zampini pcbddc->coarsening_ratio = 8; 284757de7509SStefano Zampini pcbddc->coarse_eqs_per_proc = 1; 284827b6a85dSStefano Zampini pcbddc->benign_compute_correction = PETSC_TRUE; 28491e0482f5SStefano Zampini pcbddc->nedfield = -1; 28501e0482f5SStefano Zampini pcbddc->nedglobal = PETSC_TRUE; 2851be12c134Sstefano_zampini pcbddc->graphmaxcount = PETSC_MAX_INT; 2852b96c3477SStefano Zampini pcbddc->sub_schurs_layers = -1; 2853bd2a564bSStefano Zampini pcbddc->adaptive_threshold[0] = 0.0; 2854bd2a564bSStefano Zampini pcbddc->adaptive_threshold[1] = 0.0; 2855b7eb3628SStefano Zampini 2856da1bb401SStefano Zampini /* function pointers */ 2857da1bb401SStefano Zampini pc->ops->apply = PCApply_BDDC; 285893bd9ae7SStefano Zampini pc->ops->applytranspose = PCApplyTranspose_BDDC; 2859da1bb401SStefano Zampini pc->ops->setup = PCSetUp_BDDC; 2860da1bb401SStefano Zampini pc->ops->destroy = PCDestroy_BDDC; 2861da1bb401SStefano Zampini pc->ops->setfromoptions = PCSetFromOptions_BDDC; 28626b78500eSPatrick Sanan pc->ops->view = PCView_BDDC; 28630a545947SLisandro Dalcin pc->ops->applyrichardson = NULL; 28640a545947SLisandro Dalcin pc->ops->applysymmetricleft = NULL; 28650a545947SLisandro Dalcin pc->ops->applysymmetricright = NULL; 2866534831adSStefano Zampini pc->ops->presolve = PCPreSolve_BDDC; 2867534831adSStefano Zampini pc->ops->postsolve = PCPostSolve_BDDC; 28689326c5c6Sstefano_zampini pc->ops->reset = PCReset_BDDC; 2869da1bb401SStefano Zampini 2870da1bb401SStefano Zampini /* composing function */ 28719566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDiscreteGradient_C", PCBDDCSetDiscreteGradient_BDDC)); 28729566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDivergenceMat_C", PCBDDCSetDivergenceMat_BDDC)); 28739566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetChangeOfBasisMat_C", PCBDDCSetChangeOfBasisMat_BDDC)); 28749566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesLocalIS_C", PCBDDCSetPrimalVerticesLocalIS_BDDC)); 28759566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesIS_C", PCBDDCSetPrimalVerticesIS_BDDC)); 28769566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesLocalIS_C", PCBDDCGetPrimalVerticesLocalIS_BDDC)); 28779566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesIS_C", PCBDDCGetPrimalVerticesIS_BDDC)); 28789566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetCoarseningRatio_C", PCBDDCSetCoarseningRatio_BDDC)); 28799566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevel_C", PCBDDCSetLevel_BDDC)); 28809566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetUseExactDirichlet_C", PCBDDCSetUseExactDirichlet_BDDC)); 28819566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevels_C", PCBDDCSetLevels_BDDC)); 28829566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundaries_C", PCBDDCSetDirichletBoundaries_BDDC)); 28839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundariesLocal_C", PCBDDCSetDirichletBoundariesLocal_BDDC)); 28849566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundaries_C", PCBDDCSetNeumannBoundaries_BDDC)); 28859566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundariesLocal_C", PCBDDCSetNeumannBoundariesLocal_BDDC)); 28869566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundaries_C", PCBDDCGetDirichletBoundaries_BDDC)); 28879566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundariesLocal_C", PCBDDCGetDirichletBoundariesLocal_BDDC)); 28889566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundaries_C", PCBDDCGetNeumannBoundaries_BDDC)); 28899566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundariesLocal_C", PCBDDCGetNeumannBoundariesLocal_BDDC)); 28909566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplitting_C", PCBDDCSetDofsSplitting_BDDC)); 28919566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplittingLocal_C", PCBDDCSetDofsSplittingLocal_BDDC)); 28929566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", PCBDDCSetLocalAdjacencyGraph_BDDC)); 28939566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCCreateFETIDPOperators_C", PCBDDCCreateFETIDPOperators_BDDC)); 28949566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetRHS_C", PCBDDCMatFETIDPGetRHS_BDDC)); 28959566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetSolution_C", PCBDDCMatFETIDPGetSolution_BDDC)); 28969566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", PCPreSolveChangeRHS_BDDC)); 28979566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_BDDC)); 2898da1bb401SStefano Zampini PetscFunctionReturn(0); 2899da1bb401SStefano Zampini } 290043371fb9SStefano Zampini 290143371fb9SStefano Zampini /*@C 2902f1580f4eSBarry Smith PCBDDCInitializePackage - This function initializes everything in the `PCBDDC` package. It is called 2903f1580f4eSBarry Smith from `PCInitializePackage()`. 290443371fb9SStefano Zampini 290543371fb9SStefano Zampini Level: developer 290643371fb9SStefano Zampini 2907f1580f4eSBarry Smith .seealso: `PetscInitialize()`, `PCBDDCFinalizePackage()` 290843371fb9SStefano Zampini @*/ 2909d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCInitializePackage(void) 2910d71ae5a4SJacob Faibussowitsch { 291143371fb9SStefano Zampini int i; 291243371fb9SStefano Zampini 291343371fb9SStefano Zampini PetscFunctionBegin; 291443371fb9SStefano Zampini if (PCBDDCPackageInitialized) PetscFunctionReturn(0); 291543371fb9SStefano Zampini PCBDDCPackageInitialized = PETSC_TRUE; 29169566063dSJacob Faibussowitsch PetscCall(PetscRegisterFinalize(PCBDDCFinalizePackage)); 291743371fb9SStefano Zampini 291843371fb9SStefano Zampini /* general events */ 29199566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCTopo", PC_CLASSID, &PC_BDDC_Topology[0])); 29209566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCLKSP", PC_CLASSID, &PC_BDDC_LocalSolvers[0])); 29219566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCLWor", PC_CLASSID, &PC_BDDC_LocalWork[0])); 29229566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCCorr", PC_CLASSID, &PC_BDDC_CorrectionSetUp[0])); 29239566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCASet", PC_CLASSID, &PC_BDDC_ApproxSetUp[0])); 29249566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCAApp", PC_CLASSID, &PC_BDDC_ApproxApply[0])); 29259566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCCSet", PC_CLASSID, &PC_BDDC_CoarseSetUp[0])); 29269566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCCKSP", PC_CLASSID, &PC_BDDC_CoarseSolver[0])); 29279566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCAdap", PC_CLASSID, &PC_BDDC_AdaptiveSetUp[0])); 29289566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCScal", PC_CLASSID, &PC_BDDC_Scaling[0])); 29299566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCSchr", PC_CLASSID, &PC_BDDC_Schurs[0])); 29309566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCDirS", PC_CLASSID, &PC_BDDC_Solves[0][0])); 29319566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCNeuS", PC_CLASSID, &PC_BDDC_Solves[0][1])); 29329566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister("PCBDDCCoaS", PC_CLASSID, &PC_BDDC_Solves[0][2])); 293343371fb9SStefano Zampini for (i = 1; i < PETSC_PCBDDC_MAXLEVELS; i++) { 293443371fb9SStefano Zampini char ename[32]; 293543371fb9SStefano Zampini 29369566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCTopo l%02d", i)); 29379566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Topology[i])); 29389566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCLKSP l%02d", i)); 29399566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_LocalSolvers[i])); 29409566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCLWor l%02d", i)); 29419566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_LocalWork[i])); 29429566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCorr l%02d", i)); 29439566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CorrectionSetUp[i])); 29449566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCASet l%02d", i)); 29459566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_ApproxSetUp[i])); 29469566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCAApp l%02d", i)); 29479566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_ApproxApply[i])); 29489566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCSet l%02d", i)); 29499566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CoarseSetUp[i])); 29509566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCKSP l%02d", i)); 29519566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CoarseSolver[i])); 29529566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCAdap l%02d", i)); 29539566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_AdaptiveSetUp[i])); 29549566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCScal l%02d", i)); 29559566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Scaling[i])); 29569566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCSchr l%02d", i)); 29579566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Schurs[i])); 29589566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCDirS l%02d", i)); 29599566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][0])); 29609566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCNeuS l%02d", i)); 29619566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][1])); 29629566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCoaS l%02d", i)); 29639566063dSJacob Faibussowitsch PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][2])); 296443371fb9SStefano Zampini } 296543371fb9SStefano Zampini PetscFunctionReturn(0); 296643371fb9SStefano Zampini } 296743371fb9SStefano Zampini 296843371fb9SStefano Zampini /*@C 2969f1580f4eSBarry Smith PCBDDCFinalizePackage - This function frees everything from the `PCBDDC` package. It is 2970f1580f4eSBarry Smith called from `PetscFinalize()` automatically. 297143371fb9SStefano Zampini 297243371fb9SStefano Zampini Level: developer 297343371fb9SStefano Zampini 2974f1580f4eSBarry Smith .seealso: `PetscFinalize()`, `PCBDDCInitializePackage()` 297543371fb9SStefano Zampini @*/ 2976d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCFinalizePackage(void) 2977d71ae5a4SJacob Faibussowitsch { 297843371fb9SStefano Zampini PetscFunctionBegin; 297943371fb9SStefano Zampini PCBDDCPackageInitialized = PETSC_FALSE; 298043371fb9SStefano Zampini PetscFunctionReturn(0); 298143371fb9SStefano Zampini } 2982