xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
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 
599371c9d4SSatish Balay PetscErrorCode PCSetFromOptions_BDDC(PC pc, PetscOptionItems *PetscOptionsObject) {
600c7d97c5SJed Brown   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
61e569e4e1SStefano Zampini   PetscInt nt, i;
620c7d97c5SJed Brown 
630c7d97c5SJed Brown   PetscFunctionBegin;
64d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "BDDC options");
658eeda7d8SStefano Zampini   /* Verbose debugging */
669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_check_level", "Verbose output for PCBDDC (intended for debug)", "none", pcbddc->dbg_flag, &pcbddc->dbg_flag, NULL));
67a13144ffSStefano Zampini   /* Approximate solvers */
689566063dSJacob 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));
69bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET) {
709566063dSJacob 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));
719566063dSJacob 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));
72bc960bbfSJed Brown   } else {
73bc960bbfSJed Brown     /* This flag is needed/implied by lumping */
74bc960bbfSJed Brown     pcbddc->switch_static = PETSC_TRUE;
75bc960bbfSJed Brown   }
769566063dSJacob 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));
779566063dSJacob 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));
786b78500eSPatrick Sanan   /* Primal space customization */
799566063dSJacob 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));
809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_graph_maxcount", "Maximum number of shared subdomains for a connected component", "none", pcbddc->graphmaxcount, &pcbddc->graphmaxcount, NULL));
819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_corner_selection", "Activates face-based corner selection", "none", pcbddc->corner_selection, &pcbddc->corner_selection, NULL));
829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_vertices", "Use or not corner dofs in coarse space", "none", pcbddc->use_vertices, &pcbddc->use_vertices, NULL));
839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_edges", "Use or not edge constraints in coarse space", "none", pcbddc->use_edges, &pcbddc->use_edges, NULL));
849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_faces", "Use or not face constraints in coarse space", "none", pcbddc->use_faces, &pcbddc->use_faces, NULL));
859566063dSJacob 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));
869566063dSJacob 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));
879566063dSJacob 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));
889566063dSJacob 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));
898eeda7d8SStefano Zampini   /* Change of basis */
909566063dSJacob 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));
919566063dSJacob 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));
929371c9d4SSatish Balay   if (!pcbddc->use_change_of_basis) { pcbddc->use_change_on_faces = PETSC_FALSE; }
938eeda7d8SStefano Zampini   /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */
949566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_switch_static", "Switch on static condensation ops around the interface preconditioner", "none", pcbddc->switch_static, &pcbddc->switch_static, NULL));
959566063dSJacob 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));
96e569e4e1SStefano Zampini   i = pcbddc->coarsening_ratio;
979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_coarsening_ratio", "Set coarsening ratio used in multilevel coarsening", "PCBDDCSetCoarseningRatio", i, &i, NULL));
989566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetCoarseningRatio(pc, i));
99e569e4e1SStefano Zampini   i = pcbddc->max_levels;
1009566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_levels", "Set maximum number of levels for multilevel", "PCBDDCSetLevels", i, &i, NULL));
1019566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetLevels(pc, i));
1029566063dSJacob 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));
1039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_coarse_estimates", "Use estimated eigenvalues for coarse problem", "none", pcbddc->use_coarse_estimates, &pcbddc->use_coarse_estimates, NULL));
1049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_deluxe_scaling", "Use deluxe scaling for BDDC", "none", pcbddc->use_deluxe_scaling, &pcbddc->use_deluxe_scaling, NULL));
1059566063dSJacob 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));
1069566063dSJacob 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));
1079566063dSJacob 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));
1089566063dSJacob 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));
1099566063dSJacob 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));
1109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_deluxe_singlemat", "Collapse deluxe operators", "none", pcbddc->deluxe_singlemat, &pcbddc->deluxe_singlemat, NULL));
1119566063dSJacob 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));
112bd2a564bSStefano Zampini   nt = 2;
1139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRealArray("-pc_bddc_adaptive_threshold", "Thresholds to be used for adaptive selection of constraints", "none", pcbddc->adaptive_threshold, &nt, NULL));
114bd2a564bSStefano Zampini   if (nt == 1) pcbddc->adaptive_threshold[1] = pcbddc->adaptive_threshold[0];
1159566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_adaptive_nmin", "Minimum number of constraints per connected components", "none", pcbddc->adaptive_nmin, &pcbddc->adaptive_nmin, NULL));
1169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_adaptive_nmax", "Maximum number of constraints per connected components", "none", pcbddc->adaptive_nmax, &pcbddc->adaptive_nmax, NULL));
1179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_symmetric", "Symmetric computation of primal basis functions", "none", pcbddc->symmetric_primal, &pcbddc->symmetric_primal, NULL));
1189566063dSJacob 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));
1199566063dSJacob 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));
1209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_benign_change", "Compute the pressure change of basis explicitly", "none", pcbddc->benign_change_explicit, &pcbddc->benign_change_explicit, NULL));
1219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_benign_compute_correction", "Compute the benign correction during PreSolve", "none", pcbddc->benign_compute_correction, &pcbddc->benign_compute_correction, NULL));
1229566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_nonetflux", "Automatic computation of no-net-flux quadrature weights", "none", pcbddc->compute_nonetflux, &pcbddc->compute_nonetflux, NULL));
1239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_detect_disconnected", "Detects disconnected subdomains", "none", pcbddc->detect_disconnected, &pcbddc->detect_disconnected, NULL));
1249566063dSJacob 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));
1259566063dSJacob 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));
126d0609cedSBarry Smith   PetscOptionsHeadEnd();
1270c7d97c5SJed Brown   PetscFunctionReturn(0);
1280c7d97c5SJed Brown }
1296b78500eSPatrick Sanan 
1309371c9d4SSatish Balay static PetscErrorCode PCView_BDDC(PC pc, PetscViewer viewer) {
1316b78500eSPatrick Sanan   PC_BDDC     *pcbddc = (PC_BDDC *)pc->data;
132e9627c49SStefano Zampini   PC_IS       *pcis   = (PC_IS *)pc->data;
13371783a16SStefano Zampini   PetscBool    isascii;
134e9627c49SStefano Zampini   PetscSubcomm subcomm;
135e9627c49SStefano Zampini   PetscViewer  subviewer;
1366b78500eSPatrick Sanan 
1376b78500eSPatrick Sanan   PetscFunctionBegin;
1389566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1396b78500eSPatrick Sanan   /* ASCII viewer */
1406b78500eSPatrick Sanan   if (isascii) {
1414b2aedd3SStefano Zampini     PetscMPIInt color, rank, size;
142fbad9177SStefano Zampini     PetscInt64  loc[7], gsum[6], gmax[6], gmin[6], totbenign;
143e9627c49SStefano Zampini     PetscScalar interface_size;
144e9627c49SStefano Zampini     PetscReal   ratio1 = 0., ratio2 = 0.;
145e9627c49SStefano Zampini     Vec         counter;
1466b78500eSPatrick Sanan 
147*48a46eb9SPierre Jolivet     if (!pc->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, "  Partial information available: preconditioner has not been setup yet\n"));
14863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use verbose output: %" PetscInt_FMT "\n", pcbddc->dbg_flag));
1499566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use user-defined CSR: %d\n", !!pcbddc->mat_graph->nvtxs_csr));
1509566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use local mat graph: %d\n", pcbddc->use_local_adj && !pcbddc->mat_graph->nvtxs_csr));
151e9627c49SStefano Zampini     if (pcbddc->mat_graph->twodim) {
1529566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Connectivity graph topological dimension: 2\n"));
153e9627c49SStefano Zampini     } else {
1549566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Connectivity graph topological dimension: 3\n"));
155e9627c49SStefano Zampini     }
156*48a46eb9SPierre Jolivet     if (pcbddc->graphmaxcount != PETSC_MAX_INT) PetscCall(PetscViewerASCIIPrintf(viewer, "  Graph max count: %" PetscInt_FMT "\n", pcbddc->graphmaxcount));
1579566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Corner selection: %d (selected %d)\n", pcbddc->corner_selection, pcbddc->corner_selected));
15863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use vertices: %d (vertex size %" PetscInt_FMT ")\n", pcbddc->use_vertices, pcbddc->vertex_size));
1599566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use edges: %d\n", pcbddc->use_edges));
1609566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use faces: %d\n", pcbddc->use_faces));
1619566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use true near null space: %d\n", pcbddc->use_nnsp_true));
1629566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use QR for single constraints on cc: %d\n", pcbddc->use_qr_single));
1639566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use change of basis on local edge nodes: %d\n", pcbddc->use_change_of_basis));
1649566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use change of basis on local face nodes: %d\n", pcbddc->use_change_on_faces));
1659566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  User defined change of basis matrix: %d\n", !!pcbddc->user_ChangeOfBasisMatrix));
1669566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Has change of basis matrix: %d\n", !!pcbddc->ChangeOfBasisMatrix));
1679566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Eliminate dirichlet boundary dofs: %d\n", pcbddc->eliminate_dirdofs));
1689566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Switch on static condensation ops around the interface preconditioner: %d\n", pcbddc->switch_static));
1699566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use exact dirichlet trick: %d\n", pcbddc->use_exact_dirichlet_trick));
1709566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Interface extension: %s\n", PCBDDCInterfaceExtTypes[pcbddc->interface_extension]));
17163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Multilevel max levels: %" PetscInt_FMT "\n", pcbddc->max_levels));
17263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Multilevel coarsening ratio: %" PetscInt_FMT "\n", pcbddc->coarsening_ratio));
1739566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use estimated eigs for coarse problem: %d\n", pcbddc->use_coarse_estimates));
1749566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use deluxe scaling: %d\n", pcbddc->use_deluxe_scaling));
1759566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use deluxe zerorows: %d\n", pcbddc->deluxe_zerorows));
1769566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use deluxe singlemat: %d\n", pcbddc->deluxe_singlemat));
1779566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Rebuild interface graph for Schur principal minors: %d\n", pcbddc->sub_schurs_rebuild));
17863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of dofs' layers for the computation of principal minors: %" PetscInt_FMT "\n", pcbddc->sub_schurs_layers));
1799566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use user CSR graph to compute successive layers: %d\n", pcbddc->sub_schurs_use_useradj));
180bd2a564bSStefano Zampini     if (pcbddc->adaptive_threshold[1] != pcbddc->adaptive_threshold[0]) {
18163a3b9bcSJacob 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]));
182bd2a564bSStefano Zampini     } else {
18363a3b9bcSJacob 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]));
184bd2a564bSStefano Zampini     }
18563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Min constraints / connected component: %" PetscInt_FMT "\n", pcbddc->adaptive_nmin));
18663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Max constraints / connected component: %" PetscInt_FMT "\n", pcbddc->adaptive_nmax));
1879566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Invert exact Schur complement for adaptive selection: %d\n", pcbddc->sub_schurs_exact_schur));
1889566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Symmetric computation of primal basis functions: %d\n", pcbddc->symmetric_primal));
18963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Num. Procs. to map coarse adjacency list: %" PetscInt_FMT "\n", pcbddc->coarse_adj_red));
19063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Coarse eqs per proc (significant at the coarsest level): %" PetscInt_FMT "\n", pcbddc->coarse_eqs_per_proc));
1919566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Detect disconnected: %d (filter %d)\n", pcbddc->detect_disconnected, pcbddc->detect_disconnected_filter));
1929566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Benign subspace trick: %d (change explicit %d)\n", pcbddc->benign_saddle_point, pcbddc->benign_change_explicit));
1939566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Benign subspace trick is active: %d\n", pcbddc->benign_have_null));
1949566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Algebraic computation of no-net-flux: %d\n", pcbddc->compute_nonetflux));
195b74ba07aSstefano_zampini     if (!pc->setupcalled) PetscFunctionReturn(0);
1966b78500eSPatrick Sanan 
197fbad9177SStefano Zampini     /* compute interface size */
1989566063dSJacob Faibussowitsch     PetscCall(VecSet(pcis->vec1_B, 1.0));
1999566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(pc->pmat, &counter, NULL));
2009566063dSJacob Faibussowitsch     PetscCall(VecSet(counter, 0.0));
2019566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, counter, INSERT_VALUES, SCATTER_REVERSE));
2029566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, counter, INSERT_VALUES, SCATTER_REVERSE));
2039566063dSJacob Faibussowitsch     PetscCall(VecSum(counter, &interface_size));
2049566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&counter));
205fbad9177SStefano Zampini 
206fbad9177SStefano Zampini     /* compute some statistics on the domain decomposition */
207e9627c49SStefano Zampini     gsum[0] = 1;
208fbad9177SStefano Zampini     gsum[1] = gsum[2] = gsum[3] = gsum[4] = gsum[5] = 0;
209e9627c49SStefano Zampini     loc[0]                                          = !!pcis->n;
210e9627c49SStefano Zampini     loc[1]                                          = pcis->n - pcis->n_B;
211e9627c49SStefano Zampini     loc[2]                                          = pcis->n_B;
212e9627c49SStefano Zampini     loc[3]                                          = pcbddc->local_primal_size;
213345ecf6cSStefano Zampini     loc[4]                                          = pcis->n;
214fbad9177SStefano Zampini     loc[5]                                          = pcbddc->n_local_subs > 0 ? pcbddc->n_local_subs : (pcis->n ? 1 : 0);
215fbad9177SStefano Zampini     loc[6]                                          = pcbddc->benign_n;
2169566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(loc, gsum, 6, MPIU_INT64, MPI_SUM, 0, PetscObjectComm((PetscObject)pc)));
217fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = -1;
2189566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(loc, gmax, 6, MPIU_INT64, MPI_MAX, 0, PetscObjectComm((PetscObject)pc)));
219fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = PETSC_MAX_INT;
2209566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(loc, gmin, 6, MPIU_INT64, MPI_MIN, 0, PetscObjectComm((PetscObject)pc)));
2219566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&loc[6], &totbenign, 1, MPIU_INT64, MPI_SUM, 0, PetscObjectComm((PetscObject)pc)));
222e9627c49SStefano Zampini     if (pcbddc->coarse_size) {
223e9627c49SStefano Zampini       ratio1 = pc->pmat->rmap->N / (1. * pcbddc->coarse_size);
224e9627c49SStefano Zampini       ratio2 = PetscRealPart(interface_size) / pcbddc->coarse_size;
225e9627c49SStefano Zampini     }
22663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "********************************** STATISTICS AT LEVEL %" PetscInt_FMT " **********************************\n", pcbddc->current_level));
22763a3b9bcSJacob 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));
22863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Coarsening ratios: all/coarse %" PetscInt_FMT " interface/coarse %" PetscInt_FMT "\n", (PetscInt)ratio1, (PetscInt)ratio2));
22963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Active processes : %" PetscInt_FMT "\n", (PetscInt)gsum[0]));
23063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Total subdomains : %" PetscInt_FMT "\n", (PetscInt)gsum[5]));
231*48a46eb9SPierre Jolivet     if (pcbddc->benign_have_null) PetscCall(PetscViewerASCIIPrintf(viewer, "  Benign subs      : %" PetscInt_FMT "\n", (PetscInt)totbenign));
2329566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Dofs type        :\tMIN\tMAX\tMEAN\n"));
23363a3b9bcSJacob 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])));
23463a3b9bcSJacob 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])));
23563a3b9bcSJacob 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])));
23663a3b9bcSJacob 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])));
23763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Local     subs   :\t%" PetscInt_FMT "\t%" PetscInt_FMT "\n", (PetscInt)gmin[5], (PetscInt)gmax[5]));
2389566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
23915579a77SStefano Zampini 
2409566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc), &rank));
24115579a77SStefano Zampini 
24215579a77SStefano Zampini     /* local solvers */
2439566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetSubViewer(viewer, PetscObjectComm((PetscObject)pcbddc->ksp_D), &subviewer));
244dd400576SPatrick Sanan     if (rank == 0) {
2459566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(subviewer, "--- Interior solver (rank 0)\n"));
2469566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(subviewer));
2479566063dSJacob Faibussowitsch       PetscCall(KSPView(pcbddc->ksp_D, subviewer));
2489566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(subviewer));
2499566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(subviewer, "--- Correction solver (rank 0)\n"));
2509566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(subviewer));
2519566063dSJacob Faibussowitsch       PetscCall(KSPView(pcbddc->ksp_R, subviewer));
2529566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(subviewer));
2539566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(subviewer));
25415579a77SStefano Zampini     }
2559566063dSJacob Faibussowitsch     PetscCall(PetscViewerRestoreSubViewer(viewer, PetscObjectComm((PetscObject)pcbddc->ksp_D), &subviewer));
2569566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
257e9627c49SStefano Zampini 
258fbad9177SStefano Zampini     /* the coarse problem can be handled by a different communicator */
259e9627c49SStefano Zampini     if (pcbddc->coarse_ksp) color = 1;
260e9627c49SStefano Zampini     else color = 0;
2619566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
2629566063dSJacob Faibussowitsch     PetscCall(PetscSubcommCreate(PetscObjectComm((PetscObject)pc), &subcomm));
2639566063dSJacob Faibussowitsch     PetscCall(PetscSubcommSetNumber(subcomm, PetscMin(size, 2)));
2649566063dSJacob Faibussowitsch     PetscCall(PetscSubcommSetTypeGeneral(subcomm, color, rank));
2659566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetSubViewer(viewer, PetscSubcommChild(subcomm), &subviewer));
266e9627c49SStefano Zampini     if (color == 1) {
2679566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(subviewer, "--- Coarse solver\n"));
2689566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(subviewer));
2699566063dSJacob Faibussowitsch       PetscCall(KSPView(pcbddc->coarse_ksp, subviewer));
2709566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(subviewer));
2719566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(subviewer));
272e9627c49SStefano Zampini     }
2739566063dSJacob Faibussowitsch     PetscCall(PetscViewerRestoreSubViewer(viewer, PetscSubcommChild(subcomm), &subviewer));
2749566063dSJacob Faibussowitsch     PetscCall(PetscSubcommDestroy(&subcomm));
2759566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
276e9627c49SStefano Zampini   }
2776b78500eSPatrick Sanan   PetscFunctionReturn(0);
2786b78500eSPatrick Sanan }
279a13144ffSStefano Zampini 
2809371c9d4SSatish Balay static PetscErrorCode PCBDDCSetDiscreteGradient_BDDC(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming) {
281a13144ffSStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
282a13144ffSStefano Zampini 
283a13144ffSStefano Zampini   PetscFunctionBegin;
2849566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)G));
2859566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->discretegradient));
286a13144ffSStefano Zampini   pcbddc->discretegradient = G;
287a13144ffSStefano Zampini   pcbddc->nedorder         = order > 0 ? order : -order;
288495a2a07SStefano Zampini   pcbddc->nedfield         = field;
2891e0482f5SStefano Zampini   pcbddc->nedglobal        = global;
2901e0482f5SStefano Zampini   pcbddc->conforming       = conforming;
291a13144ffSStefano Zampini   PetscFunctionReturn(0);
292a13144ffSStefano Zampini }
293a13144ffSStefano Zampini 
294a13144ffSStefano Zampini /*@
295a13144ffSStefano Zampini  PCBDDCSetDiscreteGradient - Sets the discrete gradient
296a13144ffSStefano Zampini 
297a13144ffSStefano Zampini    Collective on PC
298a13144ffSStefano Zampini 
299a13144ffSStefano Zampini    Input Parameters:
300a13144ffSStefano Zampini +  pc         - the preconditioning context
301a13144ffSStefano Zampini .  G          - the discrete gradient matrix (should be in AIJ format)
302a13144ffSStefano Zampini .  order      - the order of the Nedelec space (1 for the lowest order)
303495a2a07SStefano Zampini .  field      - the field id of the Nedelec dofs (not used if the fields have not been specified)
3041e0482f5SStefano Zampini .  global     - the type of global ordering for the rows of G
305a13144ffSStefano Zampini -  conforming - whether the mesh is conforming or not
306a13144ffSStefano Zampini 
307a13144ffSStefano Zampini    Level: advanced
308a13144ffSStefano Zampini 
30995452b02SPatrick Sanan    Notes:
31095452b02SPatrick Sanan     The discrete gradient matrix G is used to analyze the subdomain edges, and it should not contain any zero entry.
311495a2a07SStefano Zampini           For variable order spaces, the order should be set to zero.
3121e0482f5SStefano Zampini           If global is true, the rows of G should be given in global ordering for the whole dofs;
3131e0482f5SStefano Zampini           if false, the ordering should be global for the Nedelec field.
3141e0482f5SStefano 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
3151e0482f5SStefano Zampini           and geid the one for the Nedelec field.
316a13144ffSStefano Zampini 
31716b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCSetDofsSplitting()`, `PCBDDCSetDofsSplittingLocal()`
318a13144ffSStefano Zampini @*/
3199371c9d4SSatish Balay PetscErrorCode PCBDDCSetDiscreteGradient(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming) {
320a13144ffSStefano Zampini   PetscFunctionBegin;
321a13144ffSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
322a13144ffSStefano Zampini   PetscValidHeaderSpecific(G, MAT_CLASSID, 2);
323a13144ffSStefano Zampini   PetscValidLogicalCollectiveInt(pc, order, 3);
3241e0482f5SStefano Zampini   PetscValidLogicalCollectiveInt(pc, field, 4);
3251e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc, global, 5);
3261e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc, conforming, 6);
3271e0482f5SStefano Zampini   PetscCheckSameComm(pc, 1, G, 2);
328cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDiscreteGradient_C", (PC, Mat, PetscInt, PetscInt, PetscBool, PetscBool), (pc, G, order, field, global, conforming));
329a13144ffSStefano Zampini   PetscFunctionReturn(0);
330a13144ffSStefano Zampini }
331a13144ffSStefano Zampini 
3329371c9d4SSatish Balay static PetscErrorCode PCBDDCSetDivergenceMat_BDDC(PC pc, Mat divudotp, PetscBool trans, IS vl2l) {
333a198735bSStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
3346b78500eSPatrick Sanan 
335a198735bSStefano Zampini   PetscFunctionBegin;
3369566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)divudotp));
3379566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->divudotp));
338a198735bSStefano Zampini   pcbddc->divudotp          = divudotp;
3398ae0ca82SStefano Zampini   pcbddc->divudotp_trans    = trans;
340a198735bSStefano Zampini   pcbddc->compute_nonetflux = PETSC_TRUE;
341a198735bSStefano Zampini   if (vl2l) {
3429566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)vl2l));
3439566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&pcbddc->divudotp_vl2l));
344a198735bSStefano Zampini     pcbddc->divudotp_vl2l = vl2l;
345a198735bSStefano Zampini   }
346a198735bSStefano Zampini   PetscFunctionReturn(0);
347a198735bSStefano Zampini }
3483d996552SStefano Zampini 
349a198735bSStefano Zampini /*@
350a198735bSStefano Zampini  PCBDDCSetDivergenceMat - Sets the linear operator representing \int_\Omega \div {\bf u} \cdot p dx
351a198735bSStefano Zampini 
352a198735bSStefano Zampini    Collective on PC
353a198735bSStefano Zampini 
354a198735bSStefano Zampini    Input Parameters:
355a198735bSStefano Zampini +  pc - the preconditioning context
356a198735bSStefano Zampini .  divudotp - the matrix (must be of type MATIS)
3578ae0ca82SStefano Zampini .  trans - if trans if false (resp. true), then pressures are in the test (trial) space and velocities are in the trial (test) space.
35805a3bf82SStefano Zampini -  vl2l - optional index set describing the local (wrt the local matrix in divudotp) to local (wrt the local matrix in the preconditioning matrix) map for the velocities
359a198735bSStefano Zampini 
360a198735bSStefano Zampini    Level: advanced
361a198735bSStefano Zampini 
36295452b02SPatrick Sanan    Notes:
36395452b02SPatrick Sanan     This auxiliary matrix is used to compute quadrature weights representing the net-flux across subdomain boundaries
36405a3bf82SStefano Zampini           If vl2l is NULL, the local ordering for velocities in divudotp should match that of the preconditioning matrix
365a198735bSStefano Zampini 
366db781477SPatrick Sanan .seealso: `PCBDDC`
367a198735bSStefano Zampini @*/
3689371c9d4SSatish Balay PetscErrorCode PCBDDCSetDivergenceMat(PC pc, Mat divudotp, PetscBool trans, IS vl2l) {
369a198735bSStefano Zampini   PetscBool ismatis;
370a198735bSStefano Zampini 
371a198735bSStefano Zampini   PetscFunctionBegin;
372a198735bSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
373a198735bSStefano Zampini   PetscValidHeaderSpecific(divudotp, MAT_CLASSID, 2);
374a198735bSStefano Zampini   PetscCheckSameComm(pc, 1, divudotp, 2);
3758ae0ca82SStefano Zampini   PetscValidLogicalCollectiveBool(pc, trans, 3);
3761b24a7afSStefano Zampini   if (vl2l) PetscValidHeaderSpecific(vl2l, IS_CLASSID, 4);
3779566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)divudotp, MATIS, &ismatis));
37828b400f6SJacob Faibussowitsch   PetscCheck(ismatis, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Divergence matrix needs to be of type MATIS");
379cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDivergenceMat_C", (PC, Mat, PetscBool, IS), (pc, divudotp, trans, vl2l));
380a198735bSStefano Zampini   PetscFunctionReturn(0);
381a198735bSStefano Zampini }
3822d505d7fSStefano Zampini 
3839371c9d4SSatish Balay static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change, PetscBool interior) {
384b9b85e73SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
385b9b85e73SStefano Zampini 
386b9b85e73SStefano Zampini   PetscFunctionBegin;
3879566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)change));
3889566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->user_ChangeOfBasisMatrix));
389b9b85e73SStefano Zampini   pcbddc->user_ChangeOfBasisMatrix = change;
3901dd7afcfSStefano Zampini   pcbddc->change_interior          = interior;
391b9b85e73SStefano Zampini   PetscFunctionReturn(0);
392b9b85e73SStefano Zampini }
39332fe681dSStefano Zampini 
394b9b85e73SStefano Zampini /*@
395906d46d4SStefano Zampini  PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs
396b9b85e73SStefano Zampini 
397b9b85e73SStefano Zampini    Collective on PC
398b9b85e73SStefano Zampini 
399b9b85e73SStefano Zampini    Input Parameters:
400b9b85e73SStefano Zampini +  pc - the preconditioning context
4011dd7afcfSStefano Zampini .  change - the change of basis matrix
4021dd7afcfSStefano Zampini -  interior - whether or not the change of basis modifies interior dofs
403b9b85e73SStefano Zampini 
404b9b85e73SStefano Zampini    Level: intermediate
405b9b85e73SStefano Zampini 
406b9b85e73SStefano Zampini    Notes:
407b9b85e73SStefano Zampini 
408db781477SPatrick Sanan .seealso: `PCBDDC`
409b9b85e73SStefano Zampini @*/
4109371c9d4SSatish Balay PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change, PetscBool interior) {
411b9b85e73SStefano Zampini   PetscFunctionBegin;
412b9b85e73SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
413b9b85e73SStefano Zampini   PetscValidHeaderSpecific(change, MAT_CLASSID, 2);
414906d46d4SStefano Zampini   PetscCheckSameComm(pc, 1, change, 2);
415906d46d4SStefano Zampini   if (pc->mat) {
416906d46d4SStefano Zampini     PetscInt rows_c, cols_c, rows, cols;
4179566063dSJacob Faibussowitsch     PetscCall(MatGetSize(pc->mat, &rows, &cols));
4189566063dSJacob Faibussowitsch     PetscCall(MatGetSize(change, &rows_c, &cols_c));
41963a3b9bcSJacob 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);
42063a3b9bcSJacob 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);
4219566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(pc->mat, &rows, &cols));
4229566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(change, &rows_c, &cols_c));
42363a3b9bcSJacob 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);
42463a3b9bcSJacob 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);
425906d46d4SStefano Zampini   }
426cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetChangeOfBasisMat_C", (PC, Mat, PetscBool), (pc, change, interior));
427b9b85e73SStefano Zampini   PetscFunctionReturn(0);
428b9b85e73SStefano Zampini }
4292d505d7fSStefano Zampini 
4309371c9d4SSatish Balay static PetscErrorCode PCBDDCSetPrimalVerticesIS_BDDC(PC pc, IS PrimalVertices) {
43130368db7SStefano Zampini   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
43256282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
43330368db7SStefano Zampini 
43430368db7SStefano Zampini   PetscFunctionBegin;
4359566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)PrimalVertices));
436*48a46eb9SPierre Jolivet   if (pcbddc->user_primal_vertices) PetscCall(ISEqual(PrimalVertices, pcbddc->user_primal_vertices, &isequal));
4379566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices));
4389566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local));
43930368db7SStefano Zampini   pcbddc->user_primal_vertices = PrimalVertices;
44056282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
44130368db7SStefano Zampini   PetscFunctionReturn(0);
44230368db7SStefano Zampini }
443ab8c8b98SStefano Zampini 
44430368db7SStefano Zampini /*@
44530368db7SStefano Zampini  PCBDDCSetPrimalVerticesIS - Set additional user defined primal vertices in PCBDDC
44630368db7SStefano Zampini 
44730368db7SStefano Zampini    Collective
44830368db7SStefano Zampini 
44930368db7SStefano Zampini    Input Parameters:
45030368db7SStefano Zampini +  pc - the preconditioning context
45130368db7SStefano Zampini -  PrimalVertices - index set of primal vertices in global numbering (can be empty)
45230368db7SStefano Zampini 
45330368db7SStefano Zampini    Level: intermediate
45430368db7SStefano Zampini 
45530368db7SStefano Zampini    Notes:
45630368db7SStefano Zampini      Any process can list any global node
45730368db7SStefano Zampini 
458db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`, `PCBDDCGetPrimalVerticesLocalIS()`
45930368db7SStefano Zampini @*/
4609371c9d4SSatish Balay PetscErrorCode PCBDDCSetPrimalVerticesIS(PC pc, IS PrimalVertices) {
46130368db7SStefano Zampini   PetscFunctionBegin;
46230368db7SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
46330368db7SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices, IS_CLASSID, 2);
46430368db7SStefano Zampini   PetscCheckSameComm(pc, 1, PrimalVertices, 2);
465cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetPrimalVerticesIS_C", (PC, IS), (pc, PrimalVertices));
46630368db7SStefano Zampini   PetscFunctionReturn(0);
46730368db7SStefano Zampini }
4682d505d7fSStefano Zampini 
4699371c9d4SSatish Balay static PetscErrorCode PCBDDCGetPrimalVerticesIS_BDDC(PC pc, IS *is) {
4703100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
4713100ebe3SStefano Zampini 
4723100ebe3SStefano Zampini   PetscFunctionBegin;
4733100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices;
4743100ebe3SStefano Zampini   PetscFunctionReturn(0);
4753100ebe3SStefano Zampini }
4763100ebe3SStefano Zampini 
4773100ebe3SStefano Zampini /*@
4783100ebe3SStefano Zampini  PCBDDCGetPrimalVerticesIS - Get user defined primal vertices set with PCBDDCSetPrimalVerticesIS()
4793100ebe3SStefano Zampini 
4803100ebe3SStefano Zampini    Collective
4813100ebe3SStefano Zampini 
4823100ebe3SStefano Zampini    Input Parameters:
4833100ebe3SStefano Zampini .  pc - the preconditioning context
4843100ebe3SStefano Zampini 
4853100ebe3SStefano Zampini    Output Parameters:
4863100ebe3SStefano Zampini .  is - index set of primal vertices in global numbering (NULL if not set)
4873100ebe3SStefano Zampini 
4883100ebe3SStefano Zampini    Level: intermediate
4893100ebe3SStefano Zampini 
4903100ebe3SStefano Zampini    Notes:
4913100ebe3SStefano Zampini 
492db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`, `PCBDDCGetPrimalVerticesLocalIS()`
4933100ebe3SStefano Zampini @*/
4949371c9d4SSatish Balay PetscErrorCode PCBDDCGetPrimalVerticesIS(PC pc, IS *is) {
4953100ebe3SStefano Zampini   PetscFunctionBegin;
4963100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
4973100ebe3SStefano Zampini   PetscValidPointer(is, 2);
498cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetPrimalVerticesIS_C", (PC, IS *), (pc, is));
4993100ebe3SStefano Zampini   PetscFunctionReturn(0);
5003100ebe3SStefano Zampini }
5013100ebe3SStefano Zampini 
5029371c9d4SSatish Balay static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices) {
503674ae819SStefano Zampini   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
50456282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
5051e6b0712SBarry Smith 
506674ae819SStefano Zampini   PetscFunctionBegin;
5079566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)PrimalVertices));
508*48a46eb9SPierre Jolivet   if (pcbddc->user_primal_vertices_local) PetscCall(ISEqual(PrimalVertices, pcbddc->user_primal_vertices_local, &isequal));
5099566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices));
5109566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local));
51130368db7SStefano Zampini   pcbddc->user_primal_vertices_local = PrimalVertices;
51256282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
513674ae819SStefano Zampini   PetscFunctionReturn(0);
514674ae819SStefano Zampini }
5153100ebe3SStefano Zampini 
516674ae819SStefano Zampini /*@
51728509bceSStefano Zampini  PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in PCBDDC
518674ae819SStefano Zampini 
51917eb1463SStefano Zampini    Collective
520674ae819SStefano Zampini 
521674ae819SStefano Zampini    Input Parameters:
522674ae819SStefano Zampini +  pc - the preconditioning context
52317eb1463SStefano Zampini -  PrimalVertices - index set of primal vertices in local numbering (can be empty)
524674ae819SStefano Zampini 
525674ae819SStefano Zampini    Level: intermediate
526674ae819SStefano Zampini 
527674ae819SStefano Zampini    Notes:
528674ae819SStefano Zampini 
529db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesLocalIS()`
530674ae819SStefano Zampini @*/
5319371c9d4SSatish Balay PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices) {
532674ae819SStefano Zampini   PetscFunctionBegin;
533674ae819SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
534674ae819SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices, IS_CLASSID, 2);
53517eb1463SStefano Zampini   PetscCheckSameComm(pc, 1, PrimalVertices, 2);
536cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetPrimalVerticesLocalIS_C", (PC, IS), (pc, PrimalVertices));
537674ae819SStefano Zampini   PetscFunctionReturn(0);
538674ae819SStefano Zampini }
5392d505d7fSStefano Zampini 
5409371c9d4SSatish Balay static PetscErrorCode PCBDDCGetPrimalVerticesLocalIS_BDDC(PC pc, IS *is) {
5413100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
5423100ebe3SStefano Zampini 
5433100ebe3SStefano Zampini   PetscFunctionBegin;
5443100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices_local;
5453100ebe3SStefano Zampini   PetscFunctionReturn(0);
5463100ebe3SStefano Zampini }
5473100ebe3SStefano Zampini 
5483100ebe3SStefano Zampini /*@
5493100ebe3SStefano Zampini  PCBDDCGetPrimalVerticesLocalIS - Get user defined primal vertices set with PCBDDCSetPrimalVerticesLocalIS()
5503100ebe3SStefano Zampini 
5513100ebe3SStefano Zampini    Collective
5523100ebe3SStefano Zampini 
5533100ebe3SStefano Zampini    Input Parameters:
5543100ebe3SStefano Zampini .  pc - the preconditioning context
5553100ebe3SStefano Zampini 
5563100ebe3SStefano Zampini    Output Parameters:
5573100ebe3SStefano Zampini .  is - index set of primal vertices in local numbering (NULL if not set)
5583100ebe3SStefano Zampini 
5593100ebe3SStefano Zampini    Level: intermediate
5603100ebe3SStefano Zampini 
5613100ebe3SStefano Zampini    Notes:
5623100ebe3SStefano Zampini 
563db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`
5643100ebe3SStefano Zampini @*/
5659371c9d4SSatish Balay PetscErrorCode PCBDDCGetPrimalVerticesLocalIS(PC pc, IS *is) {
5663100ebe3SStefano Zampini   PetscFunctionBegin;
5673100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
5683100ebe3SStefano Zampini   PetscValidPointer(is, 2);
569cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetPrimalVerticesLocalIS_C", (PC, IS *), (pc, is));
5703100ebe3SStefano Zampini   PetscFunctionReturn(0);
5713100ebe3SStefano Zampini }
5723100ebe3SStefano Zampini 
5739371c9d4SSatish Balay static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc, PetscInt k) {
5744fad6a16SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
5754fad6a16SStefano Zampini 
5764fad6a16SStefano Zampini   PetscFunctionBegin;
5774fad6a16SStefano Zampini   pcbddc->coarsening_ratio = k;
5784fad6a16SStefano Zampini   PetscFunctionReturn(0);
5794fad6a16SStefano Zampini }
5801e6b0712SBarry Smith 
5814fad6a16SStefano Zampini /*@
58228509bceSStefano Zampini  PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel
5834fad6a16SStefano Zampini 
5844fad6a16SStefano Zampini    Logically collective on PC
5854fad6a16SStefano Zampini 
5864fad6a16SStefano Zampini    Input Parameters:
5874fad6a16SStefano Zampini +  pc - the preconditioning context
58828509bceSStefano Zampini -  k - coarsening ratio (H/h at the coarser level)
5894fad6a16SStefano Zampini 
5900f202f7eSStefano Zampini    Options Database Keys:
59167b8a455SSatish Balay .    -pc_bddc_coarsening_ratio <int> - Set coarsening ratio used in multilevel coarsening
5924fad6a16SStefano Zampini 
5934fad6a16SStefano Zampini    Level: intermediate
5944fad6a16SStefano Zampini 
5954fad6a16SStefano Zampini    Notes:
5960f202f7eSStefano Zampini      Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level
5974fad6a16SStefano Zampini 
598db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetLevels()`
5994fad6a16SStefano Zampini @*/
6009371c9d4SSatish Balay PetscErrorCode PCBDDCSetCoarseningRatio(PC pc, PetscInt k) {
6014fad6a16SStefano Zampini   PetscFunctionBegin;
6024fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
6032b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc, k, 2);
604cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetCoarseningRatio_C", (PC, PetscInt), (pc, k));
6054fad6a16SStefano Zampini   PetscFunctionReturn(0);
6064fad6a16SStefano Zampini }
6072b510759SStefano Zampini 
608b8ffe317SStefano Zampini /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */
6099371c9d4SSatish Balay static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc, PetscBool flg) {
610b8ffe317SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
611b8ffe317SStefano Zampini 
612b8ffe317SStefano Zampini   PetscFunctionBegin;
61385c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = flg;
614b8ffe317SStefano Zampini   PetscFunctionReturn(0);
615b8ffe317SStefano Zampini }
616b8ffe317SStefano Zampini 
6179371c9d4SSatish Balay PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc, PetscBool flg) {
6182b510759SStefano Zampini   PetscFunctionBegin;
6192b510759SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
620b8ffe317SStefano Zampini   PetscValidLogicalCollectiveBool(pc, flg, 2);
621cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetUseExactDirichlet_C", (PC, PetscBool), (pc, flg));
6222b510759SStefano Zampini   PetscFunctionReturn(0);
6232b510759SStefano Zampini }
6241e6b0712SBarry Smith 
6259371c9d4SSatish Balay static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc, PetscInt level) {
6264fad6a16SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
6274fad6a16SStefano Zampini 
6284fad6a16SStefano Zampini   PetscFunctionBegin;
6292b510759SStefano Zampini   pcbddc->current_level = level;
6304fad6a16SStefano Zampini   PetscFunctionReturn(0);
6314fad6a16SStefano Zampini }
6321e6b0712SBarry Smith 
6339371c9d4SSatish Balay PetscErrorCode PCBDDCSetLevel(PC pc, PetscInt level) {
634b8ffe317SStefano Zampini   PetscFunctionBegin;
635b8ffe317SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
636b8ffe317SStefano Zampini   PetscValidLogicalCollectiveInt(pc, level, 2);
637cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetLevel_C", (PC, PetscInt), (pc, level));
638b8ffe317SStefano Zampini   PetscFunctionReturn(0);
639b8ffe317SStefano Zampini }
640b8ffe317SStefano Zampini 
6419371c9d4SSatish Balay static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc, PetscInt levels) {
6422b510759SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
6432b510759SStefano Zampini 
6442b510759SStefano Zampini   PetscFunctionBegin;
6457827d75bSBarry 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);
6462b510759SStefano Zampini   pcbddc->max_levels = levels;
6472b510759SStefano Zampini   PetscFunctionReturn(0);
6482b510759SStefano Zampini }
6492b510759SStefano Zampini 
6504fad6a16SStefano Zampini /*@
65137ebbdf7SStefano Zampini  PCBDDCSetLevels - Sets the maximum number of additional levels allowed for multilevel BDDC
6524fad6a16SStefano Zampini 
6534fad6a16SStefano Zampini    Logically collective on PC
6544fad6a16SStefano Zampini 
6554fad6a16SStefano Zampini    Input Parameters:
6564fad6a16SStefano Zampini +  pc - the preconditioning context
65737ebbdf7SStefano Zampini -  levels - the maximum number of levels
6584fad6a16SStefano Zampini 
6590f202f7eSStefano Zampini    Options Database Keys:
66067b8a455SSatish Balay .    -pc_bddc_levels <int> - Set maximum number of levels for multilevel
6614fad6a16SStefano Zampini 
6624fad6a16SStefano Zampini    Level: intermediate
6634fad6a16SStefano Zampini 
6644fad6a16SStefano Zampini    Notes:
66537ebbdf7SStefano Zampini      The default value is 0, that gives the classical two-levels BDDC
6664fad6a16SStefano Zampini 
667db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetCoarseningRatio()`
6684fad6a16SStefano Zampini @*/
6699371c9d4SSatish Balay PetscErrorCode PCBDDCSetLevels(PC pc, PetscInt levels) {
6704fad6a16SStefano Zampini   PetscFunctionBegin;
6714fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
6722b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc, levels, 2);
673cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetLevels_C", (PC, PetscInt), (pc, levels));
6744fad6a16SStefano Zampini   PetscFunctionReturn(0);
6754fad6a16SStefano Zampini }
6761e6b0712SBarry Smith 
6779371c9d4SSatish Balay static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc, IS DirichletBoundaries) {
6783b03a366Sstefano_zampini   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
67956282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
6803b03a366Sstefano_zampini 
6813b03a366Sstefano_zampini   PetscFunctionBegin;
6829566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)DirichletBoundaries));
683*48a46eb9SPierre Jolivet   if (pcbddc->DirichletBoundaries) PetscCall(ISEqual(DirichletBoundaries, pcbddc->DirichletBoundaries, &isequal));
684a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
6859566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal));
6869566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundaries));
68736e030ebSStefano Zampini   pcbddc->DirichletBoundaries = DirichletBoundaries;
68856282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
6893b03a366Sstefano_zampini   PetscFunctionReturn(0);
6903b03a366Sstefano_zampini }
6911e6b0712SBarry Smith 
6923b03a366Sstefano_zampini /*@
69328509bceSStefano Zampini  PCBDDCSetDirichletBoundaries - Set IS defining Dirichlet boundaries for the global problem.
6943b03a366Sstefano_zampini 
695785d1243SStefano Zampini    Collective
6963b03a366Sstefano_zampini 
6973b03a366Sstefano_zampini    Input Parameters:
6983b03a366Sstefano_zampini +  pc - the preconditioning context
699785d1243SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries
7003b03a366Sstefano_zampini 
7013b03a366Sstefano_zampini    Level: intermediate
7023b03a366Sstefano_zampini 
7030f202f7eSStefano Zampini    Notes:
7040f202f7eSStefano Zampini      Provide the information if you used MatZeroRows/Columns routines. Any process can list any global node
7053b03a366Sstefano_zampini 
706db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetDirichletBoundariesLocal()`, `MatZeroRows()`, `MatZeroRowsColumns()`
7073b03a366Sstefano_zampini @*/
7089371c9d4SSatish Balay PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc, IS DirichletBoundaries) {
7093b03a366Sstefano_zampini   PetscFunctionBegin;
7103b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
711674ae819SStefano Zampini   PetscValidHeaderSpecific(DirichletBoundaries, IS_CLASSID, 2);
712785d1243SStefano Zampini   PetscCheckSameComm(pc, 1, DirichletBoundaries, 2);
713cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDirichletBoundaries_C", (PC, IS), (pc, DirichletBoundaries));
7143b03a366Sstefano_zampini   PetscFunctionReturn(0);
7153b03a366Sstefano_zampini }
7161e6b0712SBarry Smith 
7179371c9d4SSatish Balay static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc, IS DirichletBoundaries) {
7183b03a366Sstefano_zampini   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
71956282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
7203b03a366Sstefano_zampini 
7213b03a366Sstefano_zampini   PetscFunctionBegin;
7229566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)DirichletBoundaries));
723*48a46eb9SPierre Jolivet   if (pcbddc->DirichletBoundariesLocal) PetscCall(ISEqual(DirichletBoundaries, pcbddc->DirichletBoundariesLocal, &isequal));
724a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
7259566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal));
7269566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundaries));
727785d1243SStefano Zampini   pcbddc->DirichletBoundariesLocal = DirichletBoundaries;
72856282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7293b03a366Sstefano_zampini   PetscFunctionReturn(0);
7303b03a366Sstefano_zampini }
7313b03a366Sstefano_zampini 
7323b03a366Sstefano_zampini /*@
73382ba6b80SStefano Zampini  PCBDDCSetDirichletBoundariesLocal - Set IS defining Dirichlet boundaries for the global problem in local ordering.
7343b03a366Sstefano_zampini 
735785d1243SStefano Zampini    Collective
7363b03a366Sstefano_zampini 
7373b03a366Sstefano_zampini    Input Parameters:
7383b03a366Sstefano_zampini +  pc - the preconditioning context
73982ba6b80SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries (in local ordering)
7403b03a366Sstefano_zampini 
7413b03a366Sstefano_zampini    Level: intermediate
7423b03a366Sstefano_zampini 
7433b03a366Sstefano_zampini    Notes:
7443b03a366Sstefano_zampini 
745db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetDirichletBoundaries()`, `MatZeroRows()`, `MatZeroRowsColumns()`
7463b03a366Sstefano_zampini @*/
7479371c9d4SSatish Balay PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc, IS DirichletBoundaries) {
7483b03a366Sstefano_zampini   PetscFunctionBegin;
7493b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
7503b03a366Sstefano_zampini   PetscValidHeaderSpecific(DirichletBoundaries, IS_CLASSID, 2);
75182ba6b80SStefano Zampini   PetscCheckSameComm(pc, 1, DirichletBoundaries, 2);
752cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDirichletBoundariesLocal_C", (PC, IS), (pc, DirichletBoundaries));
7533b03a366Sstefano_zampini   PetscFunctionReturn(0);
7543b03a366Sstefano_zampini }
7553b03a366Sstefano_zampini 
7569371c9d4SSatish Balay static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc, IS NeumannBoundaries) {
7570c7d97c5SJed Brown   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
75856282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
7590c7d97c5SJed Brown 
7600c7d97c5SJed Brown   PetscFunctionBegin;
7619566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries));
762*48a46eb9SPierre Jolivet   if (pcbddc->NeumannBoundaries) PetscCall(ISEqual(NeumannBoundaries, pcbddc->NeumannBoundaries, &isequal));
763a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
7649566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal));
7659566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundaries));
76636e030ebSStefano Zampini   pcbddc->NeumannBoundaries = NeumannBoundaries;
76756282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7680c7d97c5SJed Brown   PetscFunctionReturn(0);
7690c7d97c5SJed Brown }
7701e6b0712SBarry Smith 
77157527edcSJed Brown /*@
77228509bceSStefano Zampini  PCBDDCSetNeumannBoundaries - Set IS defining Neumann boundaries for the global problem.
77357527edcSJed Brown 
774785d1243SStefano Zampini    Collective
77557527edcSJed Brown 
77657527edcSJed Brown    Input Parameters:
77757527edcSJed Brown +  pc - the preconditioning context
778785d1243SStefano Zampini -  NeumannBoundaries - parallel IS defining the Neumann boundaries
77957527edcSJed Brown 
78057527edcSJed Brown    Level: intermediate
78157527edcSJed Brown 
7820f202f7eSStefano Zampini    Notes:
7830f202f7eSStefano Zampini      Any process can list any global node
78457527edcSJed Brown 
785db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetNeumannBoundariesLocal()`
78657527edcSJed Brown @*/
7879371c9d4SSatish Balay PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc, IS NeumannBoundaries) {
7880c7d97c5SJed Brown   PetscFunctionBegin;
7890c7d97c5SJed Brown   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
790674ae819SStefano Zampini   PetscValidHeaderSpecific(NeumannBoundaries, IS_CLASSID, 2);
791785d1243SStefano Zampini   PetscCheckSameComm(pc, 1, NeumannBoundaries, 2);
792cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetNeumannBoundaries_C", (PC, IS), (pc, NeumannBoundaries));
79353cdbc3dSStefano Zampini   PetscFunctionReturn(0);
79453cdbc3dSStefano Zampini }
7951e6b0712SBarry Smith 
7969371c9d4SSatish Balay static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc, IS NeumannBoundaries) {
7970c7d97c5SJed Brown   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
79856282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
7990c7d97c5SJed Brown 
8000c7d97c5SJed Brown   PetscFunctionBegin;
8019566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries));
802*48a46eb9SPierre Jolivet   if (pcbddc->NeumannBoundariesLocal) PetscCall(ISEqual(NeumannBoundaries, pcbddc->NeumannBoundariesLocal, &isequal));
803a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
8049566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal));
8059566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundaries));
806785d1243SStefano Zampini   pcbddc->NeumannBoundariesLocal = NeumannBoundaries;
80756282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
8080c7d97c5SJed Brown   PetscFunctionReturn(0);
8090c7d97c5SJed Brown }
8100c7d97c5SJed Brown 
8110c7d97c5SJed Brown /*@
81282ba6b80SStefano Zampini  PCBDDCSetNeumannBoundariesLocal - Set IS defining Neumann boundaries for the global problem in local ordering.
8130c7d97c5SJed Brown 
814785d1243SStefano Zampini    Collective
8150c7d97c5SJed Brown 
8160c7d97c5SJed Brown    Input Parameters:
8170c7d97c5SJed Brown +  pc - the preconditioning context
81882ba6b80SStefano Zampini -  NeumannBoundaries - parallel IS defining the subdomain part of Neumann boundaries (in local ordering)
8190c7d97c5SJed Brown 
8200c7d97c5SJed Brown    Level: intermediate
8210c7d97c5SJed Brown 
8220c7d97c5SJed Brown    Notes:
8230c7d97c5SJed Brown 
824db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetNeumannBoundaries()`
8250c7d97c5SJed Brown @*/
8269371c9d4SSatish Balay PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc, IS NeumannBoundaries) {
8270c7d97c5SJed Brown   PetscFunctionBegin;
8280c7d97c5SJed Brown   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
8290c7d97c5SJed Brown   PetscValidHeaderSpecific(NeumannBoundaries, IS_CLASSID, 2);
83082ba6b80SStefano Zampini   PetscCheckSameComm(pc, 1, NeumannBoundaries, 2);
831cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetNeumannBoundariesLocal_C", (PC, IS), (pc, NeumannBoundaries));
83253cdbc3dSStefano Zampini   PetscFunctionReturn(0);
83353cdbc3dSStefano Zampini }
83453cdbc3dSStefano Zampini 
8359371c9d4SSatish Balay static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc, IS *DirichletBoundaries) {
836da1bb401SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
837da1bb401SStefano Zampini 
838da1bb401SStefano Zampini   PetscFunctionBegin;
839da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
840da1bb401SStefano Zampini   PetscFunctionReturn(0);
841da1bb401SStefano Zampini }
8421e6b0712SBarry Smith 
843da1bb401SStefano Zampini /*@
844785d1243SStefano Zampini  PCBDDCGetDirichletBoundaries - Get parallel IS for Dirichlet boundaries
845da1bb401SStefano Zampini 
846785d1243SStefano Zampini    Collective
847785d1243SStefano Zampini 
848785d1243SStefano Zampini    Input Parameters:
849785d1243SStefano Zampini .  pc - the preconditioning context
850785d1243SStefano Zampini 
851785d1243SStefano Zampini    Output Parameters:
852785d1243SStefano Zampini .  DirichletBoundaries - index set defining the Dirichlet boundaries
853785d1243SStefano Zampini 
854785d1243SStefano Zampini    Level: intermediate
855785d1243SStefano Zampini 
8560f202f7eSStefano Zampini    Notes:
8570f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetDirichletBoundaries
858785d1243SStefano Zampini 
859db781477SPatrick Sanan .seealso: `PCBDDC`
860785d1243SStefano Zampini @*/
8619371c9d4SSatish Balay PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc, IS *DirichletBoundaries) {
862785d1243SStefano Zampini   PetscFunctionBegin;
863785d1243SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
864cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetDirichletBoundaries_C", (PC, IS *), (pc, DirichletBoundaries));
865785d1243SStefano Zampini   PetscFunctionReturn(0);
866785d1243SStefano Zampini }
867785d1243SStefano Zampini 
8689371c9d4SSatish Balay static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc, IS *DirichletBoundaries) {
869785d1243SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
870785d1243SStefano Zampini 
871785d1243SStefano Zampini   PetscFunctionBegin;
872785d1243SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundariesLocal;
873785d1243SStefano Zampini   PetscFunctionReturn(0);
874785d1243SStefano Zampini }
875785d1243SStefano Zampini 
876da1bb401SStefano Zampini /*@
87782ba6b80SStefano Zampini  PCBDDCGetDirichletBoundariesLocal - Get parallel IS for Dirichlet boundaries (in local ordering)
878da1bb401SStefano Zampini 
879785d1243SStefano Zampini    Collective
880da1bb401SStefano Zampini 
881da1bb401SStefano Zampini    Input Parameters:
88228509bceSStefano Zampini .  pc - the preconditioning context
883da1bb401SStefano Zampini 
884da1bb401SStefano Zampini    Output Parameters:
88528509bceSStefano Zampini .  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
886da1bb401SStefano Zampini 
887da1bb401SStefano Zampini    Level: intermediate
888da1bb401SStefano Zampini 
889da1bb401SStefano Zampini    Notes:
8900f202f7eSStefano Zampini      The IS returned could be the same passed in earlier by the user (if provided with PCBDDCSetDirichletBoundariesLocal) or a global-to-local map of the global IS (if provided with PCBDDCSetDirichletBoundaries).
8910f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
892da1bb401SStefano Zampini 
893db781477SPatrick Sanan .seealso: `PCBDDC`
894da1bb401SStefano Zampini @*/
8959371c9d4SSatish Balay PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc, IS *DirichletBoundaries) {
896da1bb401SStefano Zampini   PetscFunctionBegin;
897da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
898cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetDirichletBoundariesLocal_C", (PC, IS *), (pc, DirichletBoundaries));
899da1bb401SStefano Zampini   PetscFunctionReturn(0);
900da1bb401SStefano Zampini }
9011e6b0712SBarry Smith 
9029371c9d4SSatish Balay static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc, IS *NeumannBoundaries) {
90353cdbc3dSStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
90453cdbc3dSStefano Zampini 
90553cdbc3dSStefano Zampini   PetscFunctionBegin;
90653cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
90753cdbc3dSStefano Zampini   PetscFunctionReturn(0);
90853cdbc3dSStefano Zampini }
9091e6b0712SBarry Smith 
91053cdbc3dSStefano Zampini /*@
911785d1243SStefano Zampini  PCBDDCGetNeumannBoundaries - Get parallel IS for Neumann boundaries
91253cdbc3dSStefano Zampini 
913785d1243SStefano Zampini    Collective
914785d1243SStefano Zampini 
915785d1243SStefano Zampini    Input Parameters:
916785d1243SStefano Zampini .  pc - the preconditioning context
917785d1243SStefano Zampini 
918785d1243SStefano Zampini    Output Parameters:
919785d1243SStefano Zampini .  NeumannBoundaries - index set defining the Neumann boundaries
920785d1243SStefano Zampini 
921785d1243SStefano Zampini    Level: intermediate
922785d1243SStefano Zampini 
9230f202f7eSStefano Zampini    Notes:
9240f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetNeumannBoundaries
925785d1243SStefano Zampini 
926db781477SPatrick Sanan .seealso: `PCBDDC`
927785d1243SStefano Zampini @*/
9289371c9d4SSatish Balay PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc, IS *NeumannBoundaries) {
929785d1243SStefano Zampini   PetscFunctionBegin;
930785d1243SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
931cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetNeumannBoundaries_C", (PC, IS *), (pc, NeumannBoundaries));
932785d1243SStefano Zampini   PetscFunctionReturn(0);
933785d1243SStefano Zampini }
934785d1243SStefano Zampini 
9359371c9d4SSatish Balay static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc, IS *NeumannBoundaries) {
936785d1243SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
937785d1243SStefano Zampini 
938785d1243SStefano Zampini   PetscFunctionBegin;
939785d1243SStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundariesLocal;
940785d1243SStefano Zampini   PetscFunctionReturn(0);
941785d1243SStefano Zampini }
942785d1243SStefano Zampini 
94353cdbc3dSStefano Zampini /*@
94482ba6b80SStefano Zampini  PCBDDCGetNeumannBoundariesLocal - Get parallel IS for Neumann boundaries (in local ordering)
94553cdbc3dSStefano Zampini 
946785d1243SStefano Zampini    Collective
94753cdbc3dSStefano Zampini 
94853cdbc3dSStefano Zampini    Input Parameters:
94928509bceSStefano Zampini .  pc - the preconditioning context
95053cdbc3dSStefano Zampini 
95153cdbc3dSStefano Zampini    Output Parameters:
95228509bceSStefano Zampini .  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
95353cdbc3dSStefano Zampini 
95453cdbc3dSStefano Zampini    Level: intermediate
95553cdbc3dSStefano Zampini 
95653cdbc3dSStefano Zampini    Notes:
9570f202f7eSStefano Zampini      The IS returned could be the same passed in earlier by the user (if provided with PCBDDCSetNeumannBoundariesLocal) or a global-to-local map of the global IS (if provided with PCBDDCSetNeumannBoundaries).
9580f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
95953cdbc3dSStefano Zampini 
960db781477SPatrick Sanan .seealso: `PCBDDC`
96153cdbc3dSStefano Zampini @*/
9629371c9d4SSatish Balay PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc, IS *NeumannBoundaries) {
96353cdbc3dSStefano Zampini   PetscFunctionBegin;
96453cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
965cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetNeumannBoundariesLocal_C", (PC, IS *), (pc, NeumannBoundaries));
9660c7d97c5SJed Brown   PetscFunctionReturn(0);
9670c7d97c5SJed Brown }
9681e6b0712SBarry Smith 
9699371c9d4SSatish Balay static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs, const PetscInt xadj[], const PetscInt adjncy[], PetscCopyMode copymode) {
97036e030ebSStefano Zampini   PC_BDDC    *pcbddc    = (PC_BDDC *)pc->data;
971da1bb401SStefano Zampini   PCBDDCGraph mat_graph = pcbddc->mat_graph;
97256282151SStefano Zampini   PetscBool   same_data = PETSC_FALSE;
97336e030ebSStefano Zampini 
97436e030ebSStefano Zampini   PetscFunctionBegin;
9758687889aSStefano Zampini   if (!nvtxs) {
97604194a47SStefano Zampini     if (copymode == PETSC_OWN_POINTER) {
9779566063dSJacob Faibussowitsch       PetscCall(PetscFree(xadj));
9789566063dSJacob Faibussowitsch       PetscCall(PetscFree(adjncy));
97904194a47SStefano Zampini     }
9809566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphResetCSR(mat_graph));
9818687889aSStefano Zampini     PetscFunctionReturn(0);
9828687889aSStefano Zampini   }
98366da6bd7Sstefano_zampini   if (mat_graph->nvtxs == nvtxs && mat_graph->freecsr) { /* we own the data */
98456282151SStefano Zampini     if (mat_graph->xadj == xadj && mat_graph->adjncy == adjncy) same_data = PETSC_TRUE;
98556282151SStefano Zampini     if (!same_data && mat_graph->xadj[nvtxs] == xadj[nvtxs]) {
9869566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(xadj, mat_graph->xadj, nvtxs + 1, &same_data));
987*48a46eb9SPierre Jolivet       if (same_data) PetscCall(PetscArraycmp(adjncy, mat_graph->adjncy, xadj[nvtxs], &same_data));
98856282151SStefano Zampini     }
98956282151SStefano Zampini   }
99056282151SStefano Zampini   if (!same_data) {
991674ae819SStefano Zampini     /* free old CSR */
9929566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphResetCSR(mat_graph));
993674ae819SStefano Zampini     /* get CSR into graph structure */
994da1bb401SStefano Zampini     if (copymode == PETSC_COPY_VALUES) {
9959566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvtxs + 1, &mat_graph->xadj));
9969566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(xadj[nvtxs], &mat_graph->adjncy));
9979566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(mat_graph->xadj, xadj, nvtxs + 1));
9989566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(mat_graph->adjncy, adjncy, xadj[nvtxs]));
999a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1000da1bb401SStefano Zampini     } else if (copymode == PETSC_OWN_POINTER) {
10011a83f524SJed Brown       mat_graph->xadj    = (PetscInt *)xadj;
10021a83f524SJed Brown       mat_graph->adjncy  = (PetscInt *)adjncy;
1003a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1004a1dbd327SStefano Zampini     } else if (copymode == PETSC_USE_POINTER) {
1005a1dbd327SStefano Zampini       mat_graph->xadj    = (PetscInt *)xadj;
1006a1dbd327SStefano Zampini       mat_graph->adjncy  = (PetscInt *)adjncy;
1007a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_FALSE;
100863a3b9bcSJacob Faibussowitsch     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported copy mode %d", copymode);
1009575ad6abSStefano Zampini     mat_graph->nvtxs_csr         = nvtxs;
101056282151SStefano Zampini     pcbddc->recompute_topography = PETSC_TRUE;
101156282151SStefano Zampini   }
101236e030ebSStefano Zampini   PetscFunctionReturn(0);
101336e030ebSStefano Zampini }
10141e6b0712SBarry Smith 
101536e030ebSStefano Zampini /*@
101654fffbccSStefano Zampini  PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local degrees of freedom.
101736e030ebSStefano Zampini 
101836e030ebSStefano Zampini    Not collective
101936e030ebSStefano Zampini 
102036e030ebSStefano Zampini    Input Parameters:
102154fffbccSStefano Zampini +  pc - the preconditioning context.
102254fffbccSStefano Zampini .  nvtxs - number of local vertices of the graph (i.e., the number of local dofs).
102354fffbccSStefano Zampini .  xadj, adjncy - the connectivity of the dofs in CSR format.
102454fffbccSStefano Zampini -  copymode - supported modes are PETSC_COPY_VALUES, PETSC_USE_POINTER or PETSC_OWN_POINTER.
102536e030ebSStefano Zampini 
102636e030ebSStefano Zampini    Level: intermediate
102736e030ebSStefano Zampini 
102895452b02SPatrick Sanan    Notes:
102995452b02SPatrick Sanan     A dof is considered connected with all local dofs if xadj[dof+1]-xadj[dof] == 1 and adjncy[xadj[dof]] is negative.
103036e030ebSStefano Zampini 
103116b07851SJed Brown .seealso: `PCBDDC`, `PetscCopyMode`
103236e030ebSStefano Zampini @*/
10339371c9d4SSatish Balay PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc, PetscInt nvtxs, const PetscInt xadj[], const PetscInt adjncy[], PetscCopyMode copymode) {
10340a545947SLisandro Dalcin   void (*f)(void) = NULL;
103536e030ebSStefano Zampini 
103636e030ebSStefano Zampini   PetscFunctionBegin;
103736e030ebSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
10388687889aSStefano Zampini   if (nvtxs) {
1039674ae819SStefano Zampini     PetscValidIntPointer(xadj, 3);
10401633d1f0SStefano Zampini     if (xadj[nvtxs]) PetscValidIntPointer(adjncy, 4);
10418687889aSStefano Zampini   }
1042cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetLocalAdjacencyGraph_C", (PC, PetscInt, const PetscInt[], const PetscInt[], PetscCopyMode), (pc, nvtxs, xadj, adjncy, copymode));
1043575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
10449566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", &f));
1045575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
10469566063dSJacob Faibussowitsch     PetscCall(PetscFree(xadj));
10479566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjncy));
1048da1bb401SStefano Zampini   }
104936e030ebSStefano Zampini   PetscFunctionReturn(0);
105036e030ebSStefano Zampini }
10511e6b0712SBarry Smith 
10529371c9d4SSatish Balay static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc, PetscInt n_is, IS ISForDofs[]) {
105363602bcaSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC *)pc->data;
105463602bcaSStefano Zampini   PetscInt  i;
105556282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
105663602bcaSStefano Zampini 
105763602bcaSStefano Zampini   PetscFunctionBegin;
105856282151SStefano Zampini   if (pcbddc->n_ISForDofsLocal == n_is) {
105956282151SStefano Zampini     for (i = 0; i < n_is; i++) {
106056282151SStefano Zampini       PetscBool isequalt;
10619566063dSJacob Faibussowitsch       PetscCall(ISEqual(ISForDofs[i], pcbddc->ISForDofsLocal[i], &isequalt));
106256282151SStefano Zampini       if (!isequalt) break;
106356282151SStefano Zampini     }
106456282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
106556282151SStefano Zampini   }
1066*48a46eb9SPierre Jolivet   for (i = 0; i < n_is; i++) PetscCall(PetscObjectReference((PetscObject)ISForDofs[i]));
106763602bcaSStefano Zampini   /* Destroy ISes if they were already set */
1068*48a46eb9SPierre Jolivet   for (i = 0; i < pcbddc->n_ISForDofsLocal; i++) PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i]));
10699566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofsLocal));
1070a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
1071*48a46eb9SPierre Jolivet   for (i = 0; i < pcbddc->n_ISForDofs; i++) PetscCall(ISDestroy(&pcbddc->ISForDofs[i]));
10729566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofs));
107363602bcaSStefano Zampini   pcbddc->n_ISForDofs = 0;
107463602bcaSStefano Zampini   /* allocate space then set */
1075*48a46eb9SPierre Jolivet   if (n_is) PetscCall(PetscMalloc1(n_is, &pcbddc->ISForDofsLocal));
10769371c9d4SSatish Balay   for (i = 0; i < n_is; i++) { pcbddc->ISForDofsLocal[i] = ISForDofs[i]; }
107763602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = n_is;
107863602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
107956282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
108063602bcaSStefano Zampini   PetscFunctionReturn(0);
108163602bcaSStefano Zampini }
108263602bcaSStefano Zampini 
108363602bcaSStefano Zampini /*@
108463602bcaSStefano Zampini  PCBDDCSetDofsSplittingLocal - Set index sets defining fields of the local subdomain matrix
108563602bcaSStefano Zampini 
108663602bcaSStefano Zampini    Collective
108763602bcaSStefano Zampini 
108863602bcaSStefano Zampini    Input Parameters:
108963602bcaSStefano Zampini +  pc - the preconditioning context
10900f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
10910f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in local ordering
109263602bcaSStefano Zampini 
109363602bcaSStefano Zampini    Level: intermediate
109463602bcaSStefano Zampini 
10950f202f7eSStefano Zampini    Notes:
10960f202f7eSStefano Zampini      n_is should be the same among processes. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
109763602bcaSStefano Zampini 
1098db781477SPatrick Sanan .seealso: `PCBDDC`
109963602bcaSStefano Zampini @*/
11009371c9d4SSatish Balay PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc, PetscInt n_is, IS ISForDofs[]) {
110163602bcaSStefano Zampini   PetscInt i;
110263602bcaSStefano Zampini 
110363602bcaSStefano Zampini   PetscFunctionBegin;
110463602bcaSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
110563602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc, n_is, 2);
110663602bcaSStefano Zampini   for (i = 0; i < n_is; i++) {
110763602bcaSStefano Zampini     PetscCheckSameComm(pc, 1, ISForDofs[i], 3);
110863602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i], IS_CLASSID, 3);
110963602bcaSStefano Zampini   }
1110cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDofsSplittingLocal_C", (PC, PetscInt, IS[]), (pc, n_is, ISForDofs));
111163602bcaSStefano Zampini   PetscFunctionReturn(0);
111263602bcaSStefano Zampini }
111363602bcaSStefano Zampini 
11149371c9d4SSatish Balay static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc, PetscInt n_is, IS ISForDofs[]) {
11159c0446d6SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC *)pc->data;
11169c0446d6SStefano Zampini   PetscInt  i;
111756282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
11189c0446d6SStefano Zampini 
11199c0446d6SStefano Zampini   PetscFunctionBegin;
112056282151SStefano Zampini   if (pcbddc->n_ISForDofs == n_is) {
112156282151SStefano Zampini     for (i = 0; i < n_is; i++) {
112256282151SStefano Zampini       PetscBool isequalt;
11239566063dSJacob Faibussowitsch       PetscCall(ISEqual(ISForDofs[i], pcbddc->ISForDofs[i], &isequalt));
112456282151SStefano Zampini       if (!isequalt) break;
112556282151SStefano Zampini     }
112656282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
112756282151SStefano Zampini   }
1128*48a46eb9SPierre Jolivet   for (i = 0; i < n_is; i++) PetscCall(PetscObjectReference((PetscObject)ISForDofs[i]));
1129da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
1130*48a46eb9SPierre Jolivet   for (i = 0; i < pcbddc->n_ISForDofs; i++) PetscCall(ISDestroy(&pcbddc->ISForDofs[i]));
11319566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofs));
1132a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
1133*48a46eb9SPierre Jolivet   for (i = 0; i < pcbddc->n_ISForDofsLocal; i++) PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i]));
11349566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofsLocal));
113563602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = 0;
1136da1bb401SStefano Zampini   /* allocate space then set */
1137*48a46eb9SPierre Jolivet   if (n_is) PetscCall(PetscMalloc1(n_is, &pcbddc->ISForDofs));
11389371c9d4SSatish Balay   for (i = 0; i < n_is; i++) { pcbddc->ISForDofs[i] = ISForDofs[i]; }
11399c0446d6SStefano Zampini   pcbddc->n_ISForDofs = n_is;
114063602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
114156282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
11429c0446d6SStefano Zampini   PetscFunctionReturn(0);
11439c0446d6SStefano Zampini }
11441e6b0712SBarry Smith 
11459c0446d6SStefano Zampini /*@
114663602bcaSStefano Zampini  PCBDDCSetDofsSplitting - Set index sets defining fields of the global matrix
11479c0446d6SStefano Zampini 
114863602bcaSStefano Zampini    Collective
11499c0446d6SStefano Zampini 
11509c0446d6SStefano Zampini    Input Parameters:
11519c0446d6SStefano Zampini +  pc - the preconditioning context
11520f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
11530f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in global ordering
11549c0446d6SStefano Zampini 
11559c0446d6SStefano Zampini    Level: intermediate
11569c0446d6SStefano Zampini 
11570f202f7eSStefano Zampini    Notes:
11580f202f7eSStefano Zampini      Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
11599c0446d6SStefano Zampini 
1160db781477SPatrick Sanan .seealso: `PCBDDC`
11619c0446d6SStefano Zampini @*/
11629371c9d4SSatish Balay PetscErrorCode PCBDDCSetDofsSplitting(PC pc, PetscInt n_is, IS ISForDofs[]) {
11632b510759SStefano Zampini   PetscInt i;
11649c0446d6SStefano Zampini 
11659c0446d6SStefano Zampini   PetscFunctionBegin;
11669c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
116763602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc, n_is, 2);
11682b510759SStefano Zampini   for (i = 0; i < n_is; i++) {
116963602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i], IS_CLASSID, 3);
1170a011d5a7Sstefano_zampini     PetscCheckSameComm(pc, 1, ISForDofs[i], 3);
11712b510759SStefano Zampini   }
1172cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDofsSplitting_C", (PC, PetscInt, IS[]), (pc, n_is, ISForDofs));
11739c0446d6SStefano Zampini   PetscFunctionReturn(0);
11749c0446d6SStefano Zampini }
1175906d46d4SStefano Zampini 
1176534831adSStefano Zampini /*
1177534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
1178534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
11799c0446d6SStefano Zampini 
1180534831adSStefano Zampini    Input Parameter:
1181966d8056SPierre Jolivet +  pc - the preconditioner context
1182534831adSStefano Zampini 
1183534831adSStefano Zampini    Application Interface Routine: PCPreSolve()
1184534831adSStefano Zampini 
1185534831adSStefano Zampini    Notes:
1186534831adSStefano Zampini      The interface routine PCPreSolve() is not usually called directly by
1187534831adSStefano Zampini    the user, but instead is called by KSPSolve().
1188534831adSStefano Zampini */
11899371c9d4SSatish Balay static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x) {
1190534831adSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC *)pc->data;
1191534831adSStefano Zampini   PC_IS    *pcis   = (PC_IS *)(pc->data);
11923972b0daSStefano Zampini   Vec       used_vec;
1193fcb54b1cSPierre Jolivet   PetscBool iscg, save_rhs = PETSC_TRUE, benign_correction_computed;
1194534831adSStefano Zampini 
1195534831adSStefano Zampini   PetscFunctionBegin;
11961f4df5f7SStefano Zampini   /* if we are working with CG, one dirichlet solve can be avoided during Krylov iterations */
119785c4d303SStefano Zampini   if (ksp) {
1198fcb54b1cSPierre Jolivet     PetscCall(PetscObjectTypeCompareAny((PetscObject)ksp, &iscg, KSPCG, KSPGROPPCG, KSPPIPECG, KSPPIPELCG, KSPPIPECGRR, ""));
1199*48a46eb9SPierre Jolivet     if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || !iscg || pc->mat != pc->pmat) PetscCall(PCBDDCSetUseExactDirichlet(pc, PETSC_FALSE));
120085c4d303SStefano Zampini   }
1201*48a46eb9SPierre Jolivet   if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || pc->mat != pc->pmat) PetscCall(PCBDDCSetUseExactDirichlet(pc, PETSC_FALSE));
12021f4df5f7SStefano Zampini 
120385c4d303SStefano Zampini   /* Creates parallel work vectors used in presolve */
1204*48a46eb9SPierre Jolivet   if (!pcbddc->original_rhs) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->original_rhs));
1205*48a46eb9SPierre Jolivet   if (!pcbddc->temp_solution) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->temp_solution));
12068d00608fSStefano Zampini 
120727b6a85dSStefano Zampini   pcbddc->temp_solution_used = PETSC_FALSE;
12083972b0daSStefano Zampini   if (x) {
12099566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)x));
12103972b0daSStefano Zampini     used_vec = x;
12118d00608fSStefano Zampini   } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */
12129566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pcbddc->temp_solution));
12133972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
12149566063dSJacob Faibussowitsch     PetscCall(VecSet(used_vec, 0.0));
121527b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
12169566063dSJacob Faibussowitsch     PetscCall(VecCopy(rhs, pcbddc->original_rhs));
1217266e20e9SStefano Zampini     save_rhs                  = PETSC_FALSE;
1218266e20e9SStefano Zampini     pcbddc->eliminate_dirdofs = PETSC_TRUE;
12193972b0daSStefano Zampini   }
12208efcfb23SStefano Zampini 
12218efcfb23SStefano Zampini   /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */
12223972b0daSStefano Zampini   if (ksp) {
1223a0cb1b98SStefano Zampini     /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */
12249566063dSJacob Faibussowitsch     PetscCall(KSPGetInitialGuessNonzero(ksp, &pcbddc->ksp_guess_nonzero));
1225*48a46eb9SPierre Jolivet     if (!pcbddc->ksp_guess_nonzero) PetscCall(VecSet(used_vec, 0.0));
12263972b0daSStefano Zampini   }
12273308cffdSStefano Zampini 
12288d00608fSStefano Zampini   pcbddc->rhs_change = PETSC_FALSE;
12293972b0daSStefano Zampini   /* Take into account zeroed rows -> change rhs and store solution removed */
123070c64980SStefano Zampini   if (rhs && pcbddc->eliminate_dirdofs) {
12313975b054SStefano Zampini     IS dirIS = NULL;
12323975b054SStefano Zampini 
1233a07ea27aSStefano Zampini     /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */
12349566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph, &dirIS));
12353975b054SStefano Zampini     if (dirIS) {
1236906d46d4SStefano Zampini       Mat_IS            *matis = (Mat_IS *)pc->pmat->data;
1237785d1243SStefano Zampini       PetscInt           dirsize, i, *is_indices;
12382b095fd8SStefano Zampini       PetscScalar       *array_x;
12392b095fd8SStefano Zampini       const PetscScalar *array_diagonal;
1240785d1243SStefano Zampini 
12419566063dSJacob Faibussowitsch       PetscCall(MatGetDiagonal(pc->pmat, pcis->vec1_global));
12429566063dSJacob Faibussowitsch       PetscCall(VecPointwiseDivide(pcis->vec1_global, rhs, pcis->vec1_global));
12439566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_global, pcis->vec2_N, INSERT_VALUES, SCATTER_FORWARD));
12449566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_global, pcis->vec2_N, INSERT_VALUES, SCATTER_FORWARD));
12459566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx, used_vec, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD));
12469566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx, used_vec, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD));
12479566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(dirIS, &dirsize));
12489566063dSJacob Faibussowitsch       PetscCall(VecGetArray(pcis->vec1_N, &array_x));
12499566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(pcis->vec2_N, &array_diagonal));
12509566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(dirIS, (const PetscInt **)&is_indices));
12512fa5cd67SKarl Rupp       for (i = 0; i < dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
12529566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(dirIS, (const PetscInt **)&is_indices));
12539566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(pcis->vec2_N, &array_diagonal));
12549566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(pcis->vec1_N, &array_x));
12559566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_N, used_vec, INSERT_VALUES, SCATTER_REVERSE));
12569566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_N, used_vec, INSERT_VALUES, SCATTER_REVERSE));
12578d00608fSStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
12589566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&dirIS));
12598efcfb23SStefano Zampini     }
1260a07ea27aSStefano Zampini   }
1261b76ba322SStefano Zampini 
12628efcfb23SStefano Zampini   /* remove the computed solution or the initial guess from the rhs */
12638d00608fSStefano Zampini   if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero)) {
126427b6a85dSStefano Zampini     /* save the original rhs */
126527b6a85dSStefano Zampini     if (save_rhs) {
12669566063dSJacob Faibussowitsch       PetscCall(VecSwap(rhs, pcbddc->original_rhs));
126727b6a85dSStefano Zampini       save_rhs = PETSC_FALSE;
12688d00608fSStefano Zampini     }
12698d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
12709566063dSJacob Faibussowitsch     PetscCall(VecScale(used_vec, -1.0));
12719566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(pc->mat, used_vec, pcbddc->original_rhs, rhs));
12729566063dSJacob Faibussowitsch     PetscCall(VecScale(used_vec, -1.0));
12739566063dSJacob Faibussowitsch     PetscCall(VecCopy(used_vec, pcbddc->temp_solution));
127427b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
12751baa6e33SBarry Smith     if (ksp) PetscCall(KSPSetInitialGuessNonzero(ksp, PETSC_FALSE));
12763308cffdSStefano Zampini   }
12779566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&used_vec));
1278b76ba322SStefano Zampini 
1279fc17d649SStefano Zampini   /* compute initial vector in benign space if needed
128027b6a85dSStefano Zampini      and remove non-benign solution from the rhs */
128127b6a85dSStefano Zampini   benign_correction_computed = PETSC_FALSE;
128208af2428SStefano Zampini   if (rhs && pcbddc->benign_compute_correction && (pcbddc->benign_have_null || pcbddc->benign_apply_coarse_only)) {
12831f4df5f7SStefano Zampini     /* compute u^*_h using ideas similar to those in Xuemin Tu's PhD thesis (see Section 4.8.1)
12841f4df5f7SStefano Zampini        Recursively apply BDDC in the multilevel case */
1285*48a46eb9SPierre Jolivet     if (!pcbddc->benign_vec) PetscCall(VecDuplicate(rhs, &pcbddc->benign_vec));
1286c69e9cc1SStefano Zampini     /* keep applying coarse solver unless we no longer have benign subdomains */
1287c69e9cc1SStefano Zampini     pcbddc->benign_apply_coarse_only = pcbddc->benign_have_null ? PETSC_TRUE : PETSC_FALSE;
128827b6a85dSStefano Zampini     if (!pcbddc->benign_skip_correction) {
12899566063dSJacob Faibussowitsch       PetscCall(PCApply_BDDC(pc, rhs, pcbddc->benign_vec));
12903bca92a6SStefano Zampini       benign_correction_computed = PETSC_TRUE;
12911baa6e33SBarry Smith       if (pcbddc->temp_solution_used) PetscCall(VecAXPY(pcbddc->temp_solution, 1.0, pcbddc->benign_vec));
12929566063dSJacob Faibussowitsch       PetscCall(VecScale(pcbddc->benign_vec, -1.0));
129327b6a85dSStefano Zampini       /* store the original rhs if not done earlier */
12941baa6e33SBarry Smith       if (save_rhs) PetscCall(VecSwap(rhs, pcbddc->original_rhs));
129527b6a85dSStefano Zampini       if (pcbddc->rhs_change) {
12969566063dSJacob Faibussowitsch         PetscCall(MatMultAdd(pc->mat, pcbddc->benign_vec, rhs, rhs));
129727b6a85dSStefano Zampini       } else {
12989566063dSJacob Faibussowitsch         PetscCall(MatMultAdd(pc->mat, pcbddc->benign_vec, pcbddc->original_rhs, rhs));
129927b6a85dSStefano Zampini       }
13000369aaf7SStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
130127b6a85dSStefano Zampini     }
130227b6a85dSStefano Zampini     pcbddc->benign_apply_coarse_only = PETSC_FALSE;
13034df7a6bfSStefano Zampini   } else {
13049566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&pcbddc->benign_vec));
13050369aaf7SStefano Zampini   }
13062d4c4fecSStefano Zampini 
13072d4c4fecSStefano Zampini   /* dbg output */
1308a198735bSStefano Zampini   if (pcbddc->dbg_flag && benign_correction_computed) {
13091f4df5f7SStefano Zampini     Vec v;
1310c69e9cc1SStefano Zampini 
13119566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_global, &v));
1312c69e9cc1SStefano Zampini     if (pcbddc->ChangeOfBasisMatrix) {
13139566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, rhs, v));
1314c69e9cc1SStefano Zampini     } else {
13159566063dSJacob Faibussowitsch       PetscCall(VecCopy(rhs, v));
1316c69e9cc1SStefano Zampini     }
13179566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, v, PETSC_TRUE));
131863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "LEVEL %" PetscInt_FMT ": is the correction benign?\n", pcbddc->current_level));
13199566063dSJacob Faibussowitsch     PetscCall(PetscScalarView(pcbddc->benign_n, pcbddc->benign_p0, pcbddc->dbg_viewer));
13209566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
13219566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&v));
13221f4df5f7SStefano Zampini   }
13230369aaf7SStefano Zampini 
13240369aaf7SStefano Zampini   /* set initial guess if using PCG */
13258ae0ca82SStefano Zampini   pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
13260369aaf7SStefano Zampini   if (x && pcbddc->use_exact_dirichlet_trick) {
13279566063dSJacob Faibussowitsch     PetscCall(VecSet(x, 0.0));
13281dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
132927b6a85dSStefano Zampini       if (benign_correction_computed) { /* we have already saved the changed rhs */
13309566063dSJacob Faibussowitsch         PetscCall(VecLockReadPop(pcis->vec1_global));
13311dd7afcfSStefano Zampini       } else {
13329566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, rhs, pcis->vec1_global));
13331dd7afcfSStefano Zampini       }
13349566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_global, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
13359566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_global, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
13361dd7afcfSStefano Zampini     } else {
13379566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D, rhs, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
13389566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D, rhs, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
13391dd7afcfSStefano Zampini     }
13409566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
13419566063dSJacob Faibussowitsch     PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D));
13429566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
13439566063dSJacob Faibussowitsch     PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D));
13441dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
13459566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_global, 0.));
13469566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, pcis->vec1_global, INSERT_VALUES, SCATTER_REVERSE));
13479566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, pcis->vec1_global, INSERT_VALUES, SCATTER_REVERSE));
13489566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcis->vec1_global, x));
13491dd7afcfSStefano Zampini     } else {
13509566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, x, INSERT_VALUES, SCATTER_REVERSE));
13519566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, x, INSERT_VALUES, SCATTER_REVERSE));
13521dd7afcfSStefano Zampini     }
13531baa6e33SBarry Smith     if (ksp) PetscCall(KSPSetInitialGuessNonzero(ksp, PETSC_TRUE));
13548ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_TRUE;
1355266e20e9SStefano Zampini   } else if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior && benign_correction_computed && pcbddc->use_exact_dirichlet_trick) {
13569566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(pcis->vec1_global));
13570369aaf7SStefano Zampini   }
1358534831adSStefano Zampini   PetscFunctionReturn(0);
1359534831adSStefano Zampini }
1360906d46d4SStefano Zampini 
1361534831adSStefano Zampini /*
1362534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
1363534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
1364534831adSStefano Zampini 
1365534831adSStefano Zampini    Input Parameter:
1366966d8056SPierre Jolivet +  pc - the preconditioner context
1367534831adSStefano Zampini 
1368534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
1369534831adSStefano Zampini 
1370534831adSStefano Zampini    Notes:
1371534831adSStefano Zampini      The interface routine PCPostSolve() is not usually called directly by
1372534831adSStefano Zampini      the user, but instead is called by KSPSolve().
1373534831adSStefano Zampini */
13749371c9d4SSatish Balay static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x) {
1375534831adSStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
1376534831adSStefano Zampini 
1377534831adSStefano Zampini   PetscFunctionBegin;
13783972b0daSStefano Zampini   /* add solution removed in presolve */
13796bcfc461SStefano Zampini   if (x && pcbddc->rhs_change) {
138027b6a85dSStefano Zampini     if (pcbddc->temp_solution_used) {
13819566063dSJacob Faibussowitsch       PetscCall(VecAXPY(x, 1.0, pcbddc->temp_solution));
1382af140850Sstefano_zampini     } else if (pcbddc->benign_compute_correction && pcbddc->benign_vec) {
13839566063dSJacob Faibussowitsch       PetscCall(VecAXPY(x, -1.0, pcbddc->benign_vec));
13843425bc38SStefano Zampini     }
1385af140850Sstefano_zampini     /* restore to original state (not for FETI-DP) */
1386af140850Sstefano_zampini     if (ksp) pcbddc->temp_solution_used = PETSC_FALSE;
138727b6a85dSStefano Zampini   }
138827b6a85dSStefano Zampini 
1389266e20e9SStefano Zampini   /* restore rhs to its original state (not needed for FETI-DP) */
13908d00608fSStefano Zampini   if (rhs && pcbddc->rhs_change) {
13919566063dSJacob Faibussowitsch     PetscCall(VecSwap(rhs, pcbddc->original_rhs));
13928d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_FALSE;
1393af140850Sstefano_zampini   }
13948efcfb23SStefano Zampini   /* restore ksp guess state */
13958efcfb23SStefano Zampini   if (ksp) {
13969566063dSJacob Faibussowitsch     PetscCall(KSPSetInitialGuessNonzero(ksp, pcbddc->ksp_guess_nonzero));
13978ae0ca82SStefano Zampini     /* reset flag for exact dirichlet trick */
13988ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
1399af140850Sstefano_zampini   }
1400534831adSStefano Zampini   PetscFunctionReturn(0);
1401534831adSStefano Zampini }
1402af140850Sstefano_zampini 
14030c7d97c5SJed Brown /*
14040c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
14050c7d97c5SJed Brown                   by setting data structures and options.
14060c7d97c5SJed Brown 
14070c7d97c5SJed Brown    Input Parameter:
140853cdbc3dSStefano Zampini +  pc - the preconditioner context
14090c7d97c5SJed Brown 
14100c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
14110c7d97c5SJed Brown 
14120c7d97c5SJed Brown    Notes:
14130c7d97c5SJed Brown      The interface routine PCSetUp() is not usually called directly by
14140c7d97c5SJed Brown      the user, but instead is called by PCApply() if necessary.
14150c7d97c5SJed Brown */
14169371c9d4SSatish Balay PetscErrorCode PCSetUp_BDDC(PC pc) {
14170c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC *)pc->data;
1418c703fcc7SStefano Zampini   PCBDDCSubSchurs sub_schurs;
14195e8657edSStefano Zampini   Mat_IS         *matis;
142008122e43SStefano Zampini   MatNullSpace    nearnullspace;
142135509ce9Sstefano_zampini   Mat             lA;
142235509ce9Sstefano_zampini   IS              lP, zerodiag = NULL;
142391e8d312SStefano Zampini   PetscInt        nrows, ncols;
142486bfa4cfSStefano Zampini   PetscMPIInt     size;
1425c703fcc7SStefano Zampini   PetscBool       computesubschurs;
14268de1fae6SStefano Zampini   PetscBool       computeconstraintsmatrix;
14273b03f7bbSStefano Zampini   PetscBool       new_nearnullspace_provided, ismatis, rl;
1428b94d7dedSBarry Smith   PetscBool       isset, issym, isspd;
14290c7d97c5SJed Brown 
14300c7d97c5SJed Brown   PetscFunctionBegin;
14319566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATIS, &ismatis));
143228b400f6SJacob Faibussowitsch   PetscCheck(ismatis, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "PCBDDC preconditioner requires matrix of type MATIS");
14339566063dSJacob Faibussowitsch   PetscCall(MatGetSize(pc->pmat, &nrows, &ncols));
14347827d75bSBarry Smith   PetscCheck(nrows == ncols, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "PCBDDC preconditioner requires a square preconditioning matrix");
14359566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
143686bfa4cfSStefano Zampini 
14375e8657edSStefano Zampini   matis = (Mat_IS *)pc->pmat->data;
1438f4ddd8eeSStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */
14393b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
144071582508SStefano Zampini      Also, BDDC builds its own KSP for the Dirichlet problem */
14413b03f7bbSStefano Zampini   rl    = pcbddc->recompute_topography;
14423b03f7bbSStefano Zampini   if (!pc->setupcalled || pc->flag == DIFFERENT_NONZERO_PATTERN) rl = PETSC_TRUE;
14431c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&rl, &pcbddc->recompute_topography, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc)));
1444c83e1ba7SStefano Zampini   if (pcbddc->recompute_topography) {
1445c83e1ba7SStefano Zampini     pcbddc->graphanalyzed    = PETSC_FALSE;
1446c83e1ba7SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1447c83e1ba7SStefano Zampini   } else {
14488de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_FALSE;
1449c83e1ba7SStefano Zampini   }
1450b087196eSStefano Zampini 
1451b087196eSStefano Zampini   /* check parameters' compatibility */
1452b7ab4a40SStefano Zampini   if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE;
1453bd2a564bSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_threshold[0] != 0.0 || pcbddc->adaptive_threshold[1] != 0.0);
145486bfa4cfSStefano Zampini   pcbddc->use_deluxe_scaling   = (PetscBool)(pcbddc->use_deluxe_scaling && size > 1);
145586bfa4cfSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_selection && size > 1);
1456bf3a8328SStefano Zampini   pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined);
1457862806e4SStefano Zampini   if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE;
1458862806e4SStefano Zampini 
14595a95e1ceSStefano Zampini   computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling);
146016909a7fSStefano Zampini 
146171582508SStefano Zampini   /* activate all connected components if the netflux has been requested */
1462bb05f991SStefano Zampini   if (pcbddc->compute_nonetflux) {
1463bb05f991SStefano Zampini     pcbddc->use_vertices = PETSC_TRUE;
1464bb05f991SStefano Zampini     pcbddc->use_edges    = PETSC_TRUE;
1465bb05f991SStefano Zampini     pcbddc->use_faces    = PETSC_TRUE;
1466bb05f991SStefano Zampini   }
1467bb05f991SStefano Zampini 
1468f4ddd8eeSStefano Zampini   /* Get stdout for dbg */
146970cf5478SStefano Zampini   if (pcbddc->dbg_flag) {
14709371c9d4SSatish Balay     if (!pcbddc->dbg_viewer) { pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc)); }
14719566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer));
14729566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIAddTab(pcbddc->dbg_viewer, 2 * pcbddc->current_level));
1473f4ddd8eeSStefano Zampini   }
1474f4ddd8eeSStefano Zampini 
1475c703fcc7SStefano Zampini   /* process topology information */
14769566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Topology[pcbddc->current_level], pc, 0, 0, 0));
147771582508SStefano Zampini   if (pcbddc->recompute_topography) {
14789566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeLocalTopologyInfo(pc));
14791baa6e33SBarry Smith     if (pcbddc->discretegradient) PetscCall(PCBDDCNedelecSupport(pc));
1480c703fcc7SStefano Zampini   }
14814f819b78SStefano Zampini   if (pcbddc->corner_selected) pcbddc->use_vertices = PETSC_TRUE;
1482a13144ffSStefano Zampini 
1483c703fcc7SStefano Zampini   /* change basis if requested by the user */
14845e8657edSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) {
14855e8657edSStefano Zampini     /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */
14865e8657edSStefano Zampini     pcbddc->use_change_of_basis = PETSC_FALSE;
14879566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeLocalMatrix(pc, pcbddc->user_ChangeOfBasisMatrix));
14885e8657edSStefano Zampini   } else {
14899566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcbddc->local_mat));
14909566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)matis->A));
14915e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
1492d16cbb6bSStefano Zampini   }
1493d16cbb6bSStefano Zampini 
14944f1b2e48SStefano Zampini   /*
1495c703fcc7SStefano Zampini      Compute change of basis on local pressures (aka zerodiag dofs) with the benign trick
14964f1b2e48SStefano Zampini      This should come earlier then PCISSetUp for extracting the correct subdomain matrices
14974f1b2e48SStefano Zampini   */
14989566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignShellMat(pc, PETSC_TRUE));
1499d16cbb6bSStefano Zampini   if (pcbddc->benign_saddle_point) {
15009f47a83aSStefano Zampini     PC_IS *pcis = (PC_IS *)pc->data;
15019f47a83aSStefano Zampini 
150205b28244SStefano Zampini     if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE;
15033b03f7bbSStefano Zampini     /* detect local saddle point and change the basis in pcbddc->local_mat */
15049566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignDetectSaddlePoint(pc, (PetscBool)(!pcbddc->recompute_topography), &zerodiag));
1505a3df083aSStefano Zampini     /* pop B0 mat from local mat */
15069566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignPopOrPushB0(pc, PETSC_TRUE));
15071dd7afcfSStefano Zampini     /* give pcis a hint to not reuse submatrices during PCISCreate */
15081dd7afcfSStefano Zampini     if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) {
15091dd7afcfSStefano Zampini       if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) {
15101dd7afcfSStefano Zampini         pcis->reusesubmatrices = PETSC_FALSE;
15111dd7afcfSStefano Zampini       } else {
1512a3df083aSStefano Zampini         pcis->reusesubmatrices = PETSC_TRUE;
15131dd7afcfSStefano Zampini       }
1514a3df083aSStefano Zampini     } else {
15159f47a83aSStefano Zampini       pcis->reusesubmatrices = PETSC_FALSE;
1516674ae819SStefano Zampini     }
1517a3df083aSStefano Zampini   }
151827b6a85dSStefano Zampini 
15198037d520SStefano Zampini   /* propagate relevant information */
1520b94d7dedSBarry Smith   PetscCall(MatIsSymmetricKnown(matis->A, &isset, &issym));
1521b94d7dedSBarry Smith   if (isset) PetscCall(MatSetOption(pcbddc->local_mat, MAT_SYMMETRIC, issym));
1522b94d7dedSBarry Smith   PetscCall(MatIsSPDKnown(matis->A, &isset, &isspd));
1523b94d7dedSBarry Smith   if (isset) PetscCall(MatSetOption(pcbddc->local_mat, MAT_SPD, isspd));
1524e496cd5dSStefano Zampini 
15255e8657edSStefano Zampini   /* Set up all the "iterative substructuring" common block without computing solvers */
15265e8657edSStefano Zampini   {
15275e8657edSStefano Zampini     Mat temp_mat;
15285e8657edSStefano Zampini 
15295e8657edSStefano Zampini     temp_mat = matis->A;
15305e8657edSStefano Zampini     matis->A = pcbddc->local_mat;
15319566063dSJacob Faibussowitsch     PetscCall(PCISSetUp(pc, PETSC_TRUE, PETSC_FALSE));
15325e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
15335e8657edSStefano Zampini     matis->A          = temp_mat;
15345e8657edSStefano Zampini   }
1535684f6988SStefano Zampini 
153681d14e9dSStefano Zampini   /* Analyze interface */
153764ac59b8SStefano Zampini   if (!pcbddc->graphanalyzed) {
15389566063dSJacob Faibussowitsch     PetscCall(PCBDDCAnalyzeInterface(pc));
15398de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1540345ecf6cSStefano Zampini     if (pcbddc->adaptive_selection && !pcbddc->use_deluxe_scaling && !pcbddc->mat_graph->twodim) {
15414247aa23Sstefano_zampini       SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot compute the adaptive primal space for a problem with 3D edges without deluxe scaling");
1542345ecf6cSStefano Zampini     }
1543a198735bSStefano Zampini     if (pcbddc->compute_nonetflux) {
1544669cc0f4SStefano Zampini       MatNullSpace nnfnnsp;
1545669cc0f4SStefano Zampini 
154628b400f6SJacob Faibussowitsch       PetscCheck(pcbddc->divudotp, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Missing divudotp operator");
15479566063dSJacob Faibussowitsch       PetscCall(PCBDDCComputeNoNetFlux(pc->pmat, pcbddc->divudotp, pcbddc->divudotp_trans, pcbddc->divudotp_vl2l, pcbddc->mat_graph, &nnfnnsp));
154871582508SStefano Zampini       /* TODO what if a nearnullspace is already attached? */
15498037d520SStefano Zampini       if (nnfnnsp) {
15509566063dSJacob Faibussowitsch         PetscCall(MatSetNearNullSpace(pc->pmat, nnfnnsp));
15519566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceDestroy(&nnfnnsp));
1552669cc0f4SStefano Zampini       }
1553674ae819SStefano Zampini     }
15548037d520SStefano Zampini   }
15559566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Topology[pcbddc->current_level], pc, 0, 0, 0));
1556fb8d54d4SStefano Zampini 
15575408967cSStefano Zampini   /* check existence of a divergence free extension, i.e.
15585408967cSStefano Zampini      b(v_I,p_0) = 0 for all v_I (raise error if not).
15595408967cSStefano Zampini      Also, check that PCBDDCBenignGetOrSetP0 works */
1560*48a46eb9SPierre Jolivet   if (pcbddc->benign_saddle_point && pcbddc->dbg_flag > 1) PetscCall(PCBDDCBenignCheck(pc, zerodiag));
15619566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&zerodiag));
156206f24817SStefano Zampini 
1563b96c3477SStefano Zampini   /* Setup local dirichlet solver ksp_D and sub_schurs solvers */
1564*48a46eb9SPierre Jolivet   if (computesubschurs && pcbddc->recompute_topography) PetscCall(PCBDDCInitSubSchurs(pc));
15659d54b7f4SStefano Zampini   /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/
1566*48a46eb9SPierre Jolivet   if (!pcbddc->use_deluxe_scaling) PetscCall(PCBDDCScalingSetUp(pc));
1567c703fcc7SStefano Zampini 
1568c703fcc7SStefano Zampini   /* finish setup solvers and do adaptive selection of constraints */
1569b334f244SStefano Zampini   sub_schurs = pcbddc->sub_schurs;
1570b334f244SStefano Zampini   if (sub_schurs && sub_schurs->schur_explicit) {
15711baa6e33SBarry Smith     if (computesubschurs) PetscCall(PCBDDCSetUpSubSchurs(pc));
15729566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetUpLocalSolvers(pc, PETSC_TRUE, PETSC_FALSE));
1573d5574798SStefano Zampini   } else {
15749566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetUpLocalSolvers(pc, PETSC_TRUE, PETSC_FALSE));
15751baa6e33SBarry Smith     if (computesubschurs) PetscCall(PCBDDCSetUpSubSchurs(pc));
15762070dbb6SStefano Zampini   }
157708122e43SStefano Zampini   if (pcbddc->adaptive_selection) {
15789566063dSJacob Faibussowitsch     PetscCall(PCBDDCAdaptiveSelection(pc));
15798de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1580b7eb3628SStefano Zampini   }
1581684f6988SStefano Zampini 
1582f4ddd8eeSStefano Zampini   /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */
1583fb8d54d4SStefano Zampini   new_nearnullspace_provided = PETSC_FALSE;
15849566063dSJacob Faibussowitsch   PetscCall(MatGetNearNullSpace(pc->pmat, &nearnullspace));
1585f4ddd8eeSStefano Zampini   if (pcbddc->onearnullspace) { /* already used nearnullspace */
1586f4ddd8eeSStefano Zampini     if (!nearnullspace) {       /* near null space attached to mat has been destroyed */
1587f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1588f4ddd8eeSStefano Zampini     } else {
1589f4ddd8eeSStefano Zampini       /* determine if the two nullspaces are different (should be lightweight) */
1590f4ddd8eeSStefano Zampini       if (nearnullspace != pcbddc->onearnullspace) {
1591f4ddd8eeSStefano Zampini         new_nearnullspace_provided = PETSC_TRUE;
1592165b64e2SStefano Zampini       } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */
1593f4ddd8eeSStefano Zampini         PetscInt         i;
1594165b64e2SStefano Zampini         const Vec       *nearnullvecs;
1595165b64e2SStefano Zampini         PetscObjectState state;
1596165b64e2SStefano Zampini         PetscInt         nnsp_size;
15979566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceGetVecs(nearnullspace, NULL, &nnsp_size, &nearnullvecs));
1598f4ddd8eeSStefano Zampini         for (i = 0; i < nnsp_size; i++) {
15999566063dSJacob Faibussowitsch           PetscCall(PetscObjectStateGet((PetscObject)nearnullvecs[i], &state));
1600165b64e2SStefano Zampini           if (pcbddc->onearnullvecs_state[i] != state) {
1601f4ddd8eeSStefano Zampini             new_nearnullspace_provided = PETSC_TRUE;
1602f4ddd8eeSStefano Zampini             break;
1603f4ddd8eeSStefano Zampini           }
1604f4ddd8eeSStefano Zampini         }
1605f4ddd8eeSStefano Zampini       }
1606f4ddd8eeSStefano Zampini     }
1607f4ddd8eeSStefano Zampini   } else {
1608f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* both nearnullspaces are null */
1609f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_FALSE;
1610f4ddd8eeSStefano Zampini     } else { /* nearnullspace attached later */
1611f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1612f4ddd8eeSStefano Zampini     }
1613f4ddd8eeSStefano Zampini   }
1614f4ddd8eeSStefano Zampini 
1615f4ddd8eeSStefano Zampini   /* Setup constraints and related work vectors */
1616727cdba6SStefano Zampini   /* reset primal space flags */
16179566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_LocalWork[pcbddc->current_level], pc, 0, 0, 0));
1618f4ddd8eeSStefano Zampini   pcbddc->new_primal_space       = PETSC_FALSE;
1619727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_FALSE;
16208de1fae6SStefano Zampini   if (computeconstraintsmatrix || new_nearnullspace_provided) {
1621727cdba6SStefano Zampini     /* It also sets the primal space flags */
16229566063dSJacob Faibussowitsch     PetscCall(PCBDDCConstraintsSetUp(pc));
16239543d0ffSStefano Zampini   }
1624e7b262bdSStefano Zampini   /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */
16259566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetUpLocalWorkVectors(pc));
16265e8657edSStefano Zampini 
16275e8657edSStefano Zampini   if (pcbddc->use_change_of_basis) {
16285e8657edSStefano Zampini     PC_IS *pcis = (PC_IS *)(pc->data);
16295e8657edSStefano Zampini 
16309566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeLocalMatrix(pc, pcbddc->ChangeOfBasisMatrix));
16314f1b2e48SStefano Zampini     if (pcbddc->benign_change) {
16329566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcbddc->benign_B0));
1633c263805aSStefano Zampini       /* pop B0 from pcbddc->local_mat */
16349566063dSJacob Faibussowitsch       PetscCall(PCBDDCBenignPopOrPushB0(pc, PETSC_TRUE));
1635c263805aSStefano Zampini     }
16365e8657edSStefano Zampini     /* get submatrices */
16379566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_IB));
16389566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_BI));
16399566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_BB));
16409566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_B_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &pcis->A_BB));
16419566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_I_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &pcis->A_IB));
16429566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_B_local, pcis->is_I_local, MAT_INITIAL_MATRIX, &pcis->A_BI));
16433975b054SStefano Zampini     /* set flag in pcis to not reuse submatrices during PCISCreate */
16443975b054SStefano Zampini     pcis->reusesubmatrices = PETSC_FALSE;
16459c6a02ceSStefano Zampini   } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) {
16469566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcbddc->local_mat));
16479566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)matis->A));
16485e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
16495e8657edSStefano Zampini   }
165035509ce9Sstefano_zampini 
165135509ce9Sstefano_zampini   /* interface pressure block row for B_C */
16529566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lP", (PetscObject *)&lP));
16539566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lA", (PetscObject *)&lA));
165435509ce9Sstefano_zampini   if (lA && lP) {
165535509ce9Sstefano_zampini     PC_IS    *pcis = (PC_IS *)pc->data;
165635509ce9Sstefano_zampini     Mat       B_BI, B_BB, Bt_BI, Bt_BB;
165735509ce9Sstefano_zampini     PetscBool issym;
1658b94d7dedSBarry Smith 
16599566063dSJacob Faibussowitsch     PetscCall(MatIsSymmetric(lA, PETSC_SMALL, &issym));
16606cc1294bSstefano_zampini     if (issym) {
16619566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_I_local, MAT_INITIAL_MATRIX, &B_BI));
16629566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_B_local, MAT_INITIAL_MATRIX, &B_BB));
16639566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(B_BI, &Bt_BI));
16649566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(B_BB, &Bt_BB));
166535509ce9Sstefano_zampini     } else {
16669566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_I_local, MAT_INITIAL_MATRIX, &B_BI));
16679566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_B_local, MAT_INITIAL_MATRIX, &B_BB));
16689566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, pcis->is_I_local, lP, MAT_INITIAL_MATRIX, &Bt_BI));
16699566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, pcis->is_B_local, lP, MAT_INITIAL_MATRIX, &Bt_BB));
167035509ce9Sstefano_zampini     }
16719566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_B_BI", (PetscObject)B_BI));
16729566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_B_BB", (PetscObject)B_BB));
16739566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_Bt_BI", (PetscObject)Bt_BI));
16749566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_Bt_BB", (PetscObject)Bt_BB));
16759566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B_BI));
16769566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B_BB));
16779566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Bt_BI));
16789566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Bt_BB));
167935509ce9Sstefano_zampini   }
16809566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_LocalWork[pcbddc->current_level], pc, 0, 0, 0));
168135509ce9Sstefano_zampini 
1682b96c3477SStefano Zampini   /* SetUp coarse and local Neumann solvers */
16839566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetUpSolvers(pc));
1684b96c3477SStefano Zampini   /* SetUp Scaling operator */
16851baa6e33SBarry Smith   if (pcbddc->use_deluxe_scaling) PetscCall(PCBDDCScalingSetUp(pc));
1686c703fcc7SStefano Zampini 
16871dd7afcfSStefano Zampini   /* mark topography as done */
168856282151SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
16890369aaf7SStefano Zampini 
16901dd7afcfSStefano Zampini   /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */
16919566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignShellMat(pc, PETSC_FALSE));
16921dd7afcfSStefano Zampini 
169358a03d70SStefano Zampini   if (pcbddc->dbg_flag) {
16949566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISubtractTab(pcbddc->dbg_viewer, 2 * pcbddc->current_level));
16959566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer));
16962b510759SStefano Zampini   }
16970c7d97c5SJed Brown   PetscFunctionReturn(0);
16980c7d97c5SJed Brown }
16990c7d97c5SJed Brown 
17000c7d97c5SJed Brown /*
170150efa1b5SStefano Zampini    PCApply_BDDC - Applies the BDDC operator to a vector.
17020c7d97c5SJed Brown 
17030c7d97c5SJed Brown    Input Parameters:
17040f202f7eSStefano Zampini +  pc - the preconditioner context
17050f202f7eSStefano Zampini -  r - input vector (global)
17060c7d97c5SJed Brown 
17070c7d97c5SJed Brown    Output Parameter:
17080c7d97c5SJed Brown .  z - output vector (global)
17090c7d97c5SJed Brown 
17100c7d97c5SJed Brown    Application Interface Routine: PCApply()
17110c7d97c5SJed Brown  */
17129371c9d4SSatish Balay PetscErrorCode PCApply_BDDC(PC pc, Vec r, Vec z) {
17130c7d97c5SJed Brown   PC_IS            *pcis   = (PC_IS *)(pc->data);
17140c7d97c5SJed Brown   PC_BDDC          *pcbddc = (PC_BDDC *)(pc->data);
1715b3338236SStefano Zampini   Mat               lA     = NULL;
1716b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
17173b03a366Sstefano_zampini   const PetscScalar one   = 1.0;
17183b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
17192617d88aSStefano Zampini   const PetscScalar zero  = 0.0;
17200c7d97c5SJed Brown   /* This code is similar to that provided in nn.c for PCNN
17210c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
1722b097fa66SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */
17230c7d97c5SJed Brown 
17240c7d97c5SJed Brown   PetscFunctionBegin;
17259566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(citation, &cited));
1726*48a46eb9SPierre Jolivet   if (pcbddc->switch_static) PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat, &lA));
1727b3338236SStefano Zampini 
17281dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
17291dd7afcfSStefano Zampini     Vec swap;
173027b6a85dSStefano Zampini 
17319566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, r, pcbddc->work_change));
17321dd7afcfSStefano Zampini     swap                = pcbddc->work_change;
17331dd7afcfSStefano Zampini     pcbddc->work_change = r;
17341dd7afcfSStefano Zampini     r                   = swap;
17351dd7afcfSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
17369cc2a9b1Sstefano_zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) {
17379566063dSJacob Faibussowitsch       PetscCall(VecCopy(r, pcis->vec1_global));
17389566063dSJacob Faibussowitsch       PetscCall(VecLockReadPush(pcis->vec1_global));
17391dd7afcfSStefano Zampini     }
17401dd7afcfSStefano Zampini   }
174127b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
17429566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, r, PETSC_TRUE));
1743efc2fbd9SStefano Zampini   }
1744bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET && !pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
17459566063dSJacob Faibussowitsch     PetscCall(VecCopy(r, z));
17460c7d97c5SJed Brown     /* First Dirichlet solve */
17479566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
17489566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
17490c7d97c5SJed Brown     /*
17500c7d97c5SJed Brown       Assembling right hand side for BDDC operator
1751b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
1752674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
17530c7d97c5SJed Brown     */
1754b097fa66SStefano Zampini     if (n_D) {
17559566063dSJacob Faibussowitsch       PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
17569566063dSJacob Faibussowitsch       PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D));
17579566063dSJacob Faibussowitsch       PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
17589566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D));
17599566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec2_D, m_one));
176016909a7fSStefano Zampini       if (pcbddc->switch_static) {
17619566063dSJacob Faibussowitsch         PetscCall(VecSet(pcis->vec1_N, 0.));
17629566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
17639566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
176416909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
17659566063dSJacob Faibussowitsch           PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N));
176616909a7fSStefano Zampini         } else {
17679566063dSJacob Faibussowitsch           PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
17689566063dSJacob Faibussowitsch           PetscCall(MatMult(lA, pcis->vec2_N, pcis->vec1_N));
17699566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
177016909a7fSStefano Zampini         }
17719566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD));
17729566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD));
17739566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
17749566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
177516909a7fSStefano Zampini       } else {
17769566063dSJacob Faibussowitsch         PetscCall(MatMult(pcis->A_BI, pcis->vec2_D, pcis->vec1_B));
177716909a7fSStefano Zampini       }
1778b097fa66SStefano Zampini     } else {
17799566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_B, zero));
1780b097fa66SStefano Zampini     }
17819566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE));
17829566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE));
17839566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingRestriction(pc, z, pcis->vec1_B));
1784b76ba322SStefano Zampini   } else {
1785*48a46eb9SPierre Jolivet     if (!pcbddc->benign_apply_coarse_only) PetscCall(PCBDDCScalingRestriction(pc, r, pcis->vec1_B));
17864fee134fSStefano Zampini   }
1787bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) {
178828b400f6SJacob Faibussowitsch     PetscCheck(pcbddc->switch_static, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "You forgot to pass -pc_bddc_switch_static");
17899566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
17909566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
1791bc960bbfSJed Brown   }
1792b76ba322SStefano Zampini 
17932617d88aSStefano Zampini   /* Apply interface preconditioner
17942617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
17959566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(pc, PETSC_FALSE));
17962617d88aSStefano Zampini 
1797674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
17989566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(pc, pcis->vec1_B, z));
1799bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) {
18009566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_D, z, INSERT_VALUES, SCATTER_REVERSE));
18019566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_D, z, INSERT_VALUES, SCATTER_REVERSE));
1802bc960bbfSJed Brown     PetscFunctionReturn(0);
1803bc960bbfSJed Brown   }
18043b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
18059566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
18069566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
1807b097fa66SStefano Zampini   if (n_B) {
180816909a7fSStefano Zampini     if (pcbddc->switch_static) {
18099566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
18109566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
18119566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
18129566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
181316909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
18149566063dSJacob Faibussowitsch         PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N));
181516909a7fSStefano Zampini       } else {
18169566063dSJacob Faibussowitsch         PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
18179566063dSJacob Faibussowitsch         PetscCall(MatMult(lA, pcis->vec2_N, pcis->vec1_N));
18189566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
181916909a7fSStefano Zampini       }
18209566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD));
18219566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD));
182216909a7fSStefano Zampini     } else {
18239566063dSJacob Faibussowitsch       PetscCall(MatMult(pcis->A_IB, pcis->vec1_B, pcis->vec3_D));
182416909a7fSStefano Zampini     }
182516909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
182616909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
18279566063dSJacob Faibussowitsch       PetscCall(MatMult(lA, pcis->vec1_D, pcis->vec3_D));
182816909a7fSStefano Zampini     } else {
18299566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_D, pcis->vec1_N));
18309566063dSJacob Faibussowitsch       PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N));
18319566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec2_N, pcis->vec3_D));
183216909a7fSStefano Zampini     }
1833b097fa66SStefano Zampini   }
18349566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
18359566063dSJacob Faibussowitsch   PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec3_D, pcis->vec4_D));
18369566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
18379566063dSJacob Faibussowitsch   PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec4_D));
1838efc2fbd9SStefano Zampini 
18398ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1840b097fa66SStefano Zampini     if (pcbddc->switch_static) {
18419566063dSJacob Faibussowitsch       PetscCall(VecAXPBYPCZ(pcis->vec2_D, m_one, one, m_one, pcis->vec4_D, pcis->vec1_D));
1842b097fa66SStefano Zampini     } else {
18439566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec2_D, m_one, m_one, pcis->vec4_D));
1844b097fa66SStefano Zampini     }
18459566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE));
18469566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE));
1847b097fa66SStefano Zampini   } else {
1848b097fa66SStefano Zampini     if (pcbddc->switch_static) {
18499566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec4_D, one, m_one, pcis->vec1_D));
1850b097fa66SStefano Zampini     } else {
18519566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec4_D, m_one));
1852b097fa66SStefano Zampini     }
18539566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE));
18549566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE));
1855b097fa66SStefano Zampini   }
185627b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
18571baa6e33SBarry Smith     if (pcbddc->benign_apply_coarse_only) PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n));
18589566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, z, PETSC_FALSE));
1859efc2fbd9SStefano Zampini   }
18601f4df5f7SStefano Zampini 
18611dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1862f913dca9SStefano Zampini     pcbddc->work_change = r;
18639566063dSJacob Faibussowitsch     PetscCall(VecCopy(z, pcbddc->work_change));
18649566063dSJacob Faibussowitsch     PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcbddc->work_change, z));
18651dd7afcfSStefano Zampini   }
18660c7d97c5SJed Brown   PetscFunctionReturn(0);
18670c7d97c5SJed Brown }
186850efa1b5SStefano Zampini 
186950efa1b5SStefano Zampini /*
187050efa1b5SStefano Zampini    PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector.
187150efa1b5SStefano Zampini 
187250efa1b5SStefano Zampini    Input Parameters:
18730f202f7eSStefano Zampini +  pc - the preconditioner context
18740f202f7eSStefano Zampini -  r - input vector (global)
187550efa1b5SStefano Zampini 
187650efa1b5SStefano Zampini    Output Parameter:
187750efa1b5SStefano Zampini .  z - output vector (global)
187850efa1b5SStefano Zampini 
187950efa1b5SStefano Zampini    Application Interface Routine: PCApplyTranspose()
188050efa1b5SStefano Zampini  */
18819371c9d4SSatish Balay PetscErrorCode PCApplyTranspose_BDDC(PC pc, Vec r, Vec z) {
188250efa1b5SStefano Zampini   PC_IS            *pcis   = (PC_IS *)(pc->data);
188350efa1b5SStefano Zampini   PC_BDDC          *pcbddc = (PC_BDDC *)(pc->data);
1884b3338236SStefano Zampini   Mat               lA     = NULL;
1885b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
188650efa1b5SStefano Zampini   const PetscScalar one   = 1.0;
188750efa1b5SStefano Zampini   const PetscScalar m_one = -1.0;
188850efa1b5SStefano Zampini   const PetscScalar zero  = 0.0;
188950efa1b5SStefano Zampini 
189050efa1b5SStefano Zampini   PetscFunctionBegin;
18919566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(citation, &cited));
1892*48a46eb9SPierre Jolivet   if (pcbddc->switch_static) PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat, &lA));
18931dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
18941dd7afcfSStefano Zampini     Vec swap;
189527b6a85dSStefano Zampini 
18969566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, r, pcbddc->work_change));
18971dd7afcfSStefano Zampini     swap                = pcbddc->work_change;
18981dd7afcfSStefano Zampini     pcbddc->work_change = r;
18991dd7afcfSStefano Zampini     r                   = swap;
190027b6a85dSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
19018ae0ca82SStefano Zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->exact_dirichlet_trick_app && pcbddc->change_interior) {
19029566063dSJacob Faibussowitsch       PetscCall(VecCopy(r, pcis->vec1_global));
19039566063dSJacob Faibussowitsch       PetscCall(VecLockReadPush(pcis->vec1_global));
19041dd7afcfSStefano Zampini     }
190527b6a85dSStefano Zampini   }
190627b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
19079566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, r, PETSC_TRUE));
1908537c1cdfSStefano Zampini   }
19098ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
19109566063dSJacob Faibussowitsch     PetscCall(VecCopy(r, z));
191150efa1b5SStefano Zampini     /* First Dirichlet solve */
19129566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
19139566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
191450efa1b5SStefano Zampini     /*
191550efa1b5SStefano Zampini       Assembling right hand side for BDDC operator
1916b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
191750efa1b5SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
191850efa1b5SStefano Zampini     */
1919b097fa66SStefano Zampini     if (n_D) {
19209566063dSJacob Faibussowitsch       PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
19219566063dSJacob Faibussowitsch       PetscCall(KSPSolveTranspose(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D));
19229566063dSJacob Faibussowitsch       PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
19239566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D));
19249566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec2_D, m_one));
192516909a7fSStefano Zampini       if (pcbddc->switch_static) {
19269566063dSJacob Faibussowitsch         PetscCall(VecSet(pcis->vec1_N, 0.));
19279566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
19289566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
192916909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
19309566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N));
193116909a7fSStefano Zampini         } else {
19329566063dSJacob Faibussowitsch           PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
19339566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(lA, pcis->vec2_N, pcis->vec1_N));
19349566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
193516909a7fSStefano Zampini         }
19369566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD));
19379566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD));
19389566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
19399566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
194016909a7fSStefano Zampini       } else {
19419566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcis->A_IB, pcis->vec2_D, pcis->vec1_B));
194216909a7fSStefano Zampini       }
1943b097fa66SStefano Zampini     } else {
19449566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_B, zero));
1945b097fa66SStefano Zampini     }
19469566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE));
19479566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE));
19489566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingRestriction(pc, z, pcis->vec1_B));
194950efa1b5SStefano Zampini   } else {
19509566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingRestriction(pc, r, pcis->vec1_B));
195150efa1b5SStefano Zampini   }
195250efa1b5SStefano Zampini 
195350efa1b5SStefano Zampini   /* Apply interface preconditioner
195450efa1b5SStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
19559566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(pc, PETSC_TRUE));
195650efa1b5SStefano Zampini 
195750efa1b5SStefano Zampini   /* Apply transpose of partition of unity operator */
19589566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(pc, pcis->vec1_B, z));
195950efa1b5SStefano Zampini 
196050efa1b5SStefano Zampini   /* Second Dirichlet solve and assembling of output */
19619566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
19629566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
1963b097fa66SStefano Zampini   if (n_B) {
196416909a7fSStefano Zampini     if (pcbddc->switch_static) {
19659566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
19669566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
19679566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
19689566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
196916909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
19709566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N));
197116909a7fSStefano Zampini       } else {
19729566063dSJacob Faibussowitsch         PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
19739566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(lA, pcis->vec2_N, pcis->vec1_N));
19749566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
197516909a7fSStefano Zampini       }
19769566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD));
19779566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD));
197816909a7fSStefano Zampini     } else {
19799566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcis->A_BI, pcis->vec1_B, pcis->vec3_D));
198016909a7fSStefano Zampini     }
198116909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
198216909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
19839566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(lA, pcis->vec1_D, pcis->vec3_D));
198416909a7fSStefano Zampini     } else {
19859566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_D, pcis->vec1_N));
19869566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N));
19879566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec2_N, pcis->vec3_D));
198816909a7fSStefano Zampini     }
1989b097fa66SStefano Zampini   }
19909566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
19919566063dSJacob Faibussowitsch   PetscCall(KSPSolveTranspose(pcbddc->ksp_D, pcis->vec3_D, pcis->vec4_D));
19929566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
19939566063dSJacob Faibussowitsch   PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec4_D));
19948ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1995b097fa66SStefano Zampini     if (pcbddc->switch_static) {
19969566063dSJacob Faibussowitsch       PetscCall(VecAXPBYPCZ(pcis->vec2_D, m_one, one, m_one, pcis->vec4_D, pcis->vec1_D));
1997b097fa66SStefano Zampini     } else {
19989566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec2_D, m_one, m_one, pcis->vec4_D));
1999b097fa66SStefano Zampini     }
20009566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE));
20019566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE));
2002b097fa66SStefano Zampini   } else {
2003b097fa66SStefano Zampini     if (pcbddc->switch_static) {
20049566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec4_D, one, m_one, pcis->vec1_D));
2005b097fa66SStefano Zampini     } else {
20069566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec4_D, m_one));
2007b097fa66SStefano Zampini     }
20089566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE));
20099566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE));
2010b097fa66SStefano Zampini   }
201127b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
20129566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, z, PETSC_FALSE));
2013537c1cdfSStefano Zampini   }
20141dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2015f913dca9SStefano Zampini     pcbddc->work_change = r;
20169566063dSJacob Faibussowitsch     PetscCall(VecCopy(z, pcbddc->work_change));
20179566063dSJacob Faibussowitsch     PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcbddc->work_change, z));
20181dd7afcfSStefano Zampini   }
201950efa1b5SStefano Zampini   PetscFunctionReturn(0);
202050efa1b5SStefano Zampini }
2021674ae819SStefano Zampini 
20229371c9d4SSatish Balay PetscErrorCode PCReset_BDDC(PC pc) {
2023da1bb401SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
20249326c5c6Sstefano_zampini   PC_IS   *pcis   = (PC_IS *)pc->data;
20259326c5c6Sstefano_zampini   KSP      kspD, kspR, kspC;
2026da1bb401SStefano Zampini 
2027da1bb401SStefano Zampini   PetscFunctionBegin;
2028674ae819SStefano Zampini   /* free BDDC custom data  */
20299566063dSJacob Faibussowitsch   PetscCall(PCBDDCResetCustomization(pc));
2030674ae819SStefano Zampini   /* destroy objects related to topography */
20319566063dSJacob Faibussowitsch   PetscCall(PCBDDCResetTopography(pc));
203234a97f8cSStefano Zampini   /* destroy objects for scaling operator */
20339566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingDestroy(pc));
2034674ae819SStefano Zampini   /* free solvers stuff */
20359566063dSJacob Faibussowitsch   PetscCall(PCBDDCResetSolvers(pc));
203662a6ff1dSStefano Zampini   /* free global vectors needed in presolve */
20379566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->temp_solution));
20389566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->original_rhs));
20391dd7afcfSStefano Zampini   /* free data created by PCIS */
20409566063dSJacob Faibussowitsch   PetscCall(PCISDestroy(pc));
20419326c5c6Sstefano_zampini 
20429326c5c6Sstefano_zampini   /* restore defaults */
20439326c5c6Sstefano_zampini   kspD = pcbddc->ksp_D;
20449326c5c6Sstefano_zampini   kspR = pcbddc->ksp_R;
20459326c5c6Sstefano_zampini   kspC = pcbddc->coarse_ksp;
20469566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(pc->data, sizeof(*pcbddc)));
20479326c5c6Sstefano_zampini   pcis->n_neigh                     = -1;
20489326c5c6Sstefano_zampini   pcis->scaling_factor              = 1.0;
20499326c5c6Sstefano_zampini   pcis->reusesubmatrices            = PETSC_TRUE;
20509326c5c6Sstefano_zampini   pcbddc->use_local_adj             = PETSC_TRUE;
20519326c5c6Sstefano_zampini   pcbddc->use_vertices              = PETSC_TRUE;
20529326c5c6Sstefano_zampini   pcbddc->use_edges                 = PETSC_TRUE;
20539326c5c6Sstefano_zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
20549326c5c6Sstefano_zampini   pcbddc->vertex_size               = 1;
20559326c5c6Sstefano_zampini   pcbddc->recompute_topography      = PETSC_TRUE;
20569326c5c6Sstefano_zampini   pcbddc->coarse_size               = -1;
20579326c5c6Sstefano_zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
20589326c5c6Sstefano_zampini   pcbddc->coarsening_ratio          = 8;
20599326c5c6Sstefano_zampini   pcbddc->coarse_eqs_per_proc       = 1;
20609326c5c6Sstefano_zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
20619326c5c6Sstefano_zampini   pcbddc->nedfield                  = -1;
20629326c5c6Sstefano_zampini   pcbddc->nedglobal                 = PETSC_TRUE;
20639326c5c6Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
20649326c5c6Sstefano_zampini   pcbddc->sub_schurs_layers         = -1;
20659326c5c6Sstefano_zampini   pcbddc->ksp_D                     = kspD;
20669326c5c6Sstefano_zampini   pcbddc->ksp_R                     = kspR;
20679326c5c6Sstefano_zampini   pcbddc->coarse_ksp                = kspC;
20689326c5c6Sstefano_zampini   PetscFunctionReturn(0);
20699326c5c6Sstefano_zampini }
20709326c5c6Sstefano_zampini 
20719371c9d4SSatish Balay PetscErrorCode PCDestroy_BDDC(PC pc) {
20729326c5c6Sstefano_zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
20739326c5c6Sstefano_zampini 
20749326c5c6Sstefano_zampini   PetscFunctionBegin;
20759566063dSJacob Faibussowitsch   PetscCall(PCReset_BDDC(pc));
20769566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcbddc->ksp_D));
20779566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcbddc->ksp_R));
20789566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcbddc->coarse_ksp));
20799566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDiscreteGradient_C", NULL));
20809566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDivergenceMat_C", NULL));
20819566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetChangeOfBasisMat_C", NULL));
20829566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesLocalIS_C", NULL));
20839566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesIS_C", NULL));
208432fe681dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesLocalIS_C", NULL));
208532fe681dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesIS_C", NULL));
20869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetCoarseningRatio_C", NULL));
20879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevel_C", NULL));
20889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetUseExactDirichlet_C", NULL));
20899566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevels_C", NULL));
20909566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundaries_C", NULL));
20919566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundariesLocal_C", NULL));
20929566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundaries_C", NULL));
20939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundariesLocal_C", NULL));
20949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundaries_C", NULL));
20959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundariesLocal_C", NULL));
20969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundaries_C", NULL));
20979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundariesLocal_C", NULL));
20989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplitting_C", NULL));
20999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplittingLocal_C", NULL));
21009566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", NULL));
21019566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCCreateFETIDPOperators_C", NULL));
21029566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetRHS_C", NULL));
21039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetSolution_C", NULL));
21049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", NULL));
21059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", NULL));
21069566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
2107da1bb401SStefano Zampini   PetscFunctionReturn(0);
2108da1bb401SStefano Zampini }
21091e6b0712SBarry Smith 
21109371c9d4SSatish Balay static PetscErrorCode PCSetCoordinates_BDDC(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords) {
2111ab8c8b98SStefano Zampini   PC_BDDC    *pcbddc    = (PC_BDDC *)pc->data;
2112ab8c8b98SStefano Zampini   PCBDDCGraph mat_graph = pcbddc->mat_graph;
2113ab8c8b98SStefano Zampini 
2114ab8c8b98SStefano Zampini   PetscFunctionBegin;
21159566063dSJacob Faibussowitsch   PetscCall(PetscFree(mat_graph->coords));
21169566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nloc * dim, &mat_graph->coords));
21179566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(mat_graph->coords, coords, nloc * dim));
2118ab8c8b98SStefano Zampini   mat_graph->cnloc             = nloc;
2119ab8c8b98SStefano Zampini   mat_graph->cdim              = dim;
2120ab8c8b98SStefano Zampini   mat_graph->cloc              = PETSC_FALSE;
21214f819b78SStefano Zampini   /* flg setup */
21224f819b78SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
21234f819b78SStefano Zampini   pcbddc->corner_selected      = PETSC_FALSE;
2124ab8c8b98SStefano Zampini   PetscFunctionReturn(0);
2125ab8c8b98SStefano Zampini }
2126ab8c8b98SStefano Zampini 
21279371c9d4SSatish Balay static PetscErrorCode PCPreSolveChangeRHS_BDDC(PC pc, PetscBool *change) {
2128a06fd7f2SStefano Zampini   PetscFunctionBegin;
2129a06fd7f2SStefano Zampini   *change = PETSC_TRUE;
2130a06fd7f2SStefano Zampini   PetscFunctionReturn(0);
2131a06fd7f2SStefano Zampini }
2132a06fd7f2SStefano Zampini 
21339371c9d4SSatish Balay static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) {
2134674ae819SStefano Zampini   FETIDPMat_ctx mat_ctx;
2135266e20e9SStefano Zampini   Vec           work;
21363425bc38SStefano Zampini   PC_IS        *pcis;
21373425bc38SStefano Zampini   PC_BDDC      *pcbddc;
21380c7d97c5SJed Brown 
21393425bc38SStefano Zampini   PetscFunctionBegin;
21409566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx));
21413425bc38SStefano Zampini   pcis   = (PC_IS *)mat_ctx->pc->data;
21423425bc38SStefano Zampini   pcbddc = (PC_BDDC *)mat_ctx->pc->data;
21433425bc38SStefano Zampini 
21449566063dSJacob Faibussowitsch   PetscCall(VecSet(fetidp_flux_rhs, 0.0));
2145229984c5Sstefano_zampini   /* copy rhs since we may change it during PCPreSolve_BDDC */
2146*48a46eb9SPierre Jolivet   if (!pcbddc->original_rhs) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->original_rhs));
21476cc1294bSstefano_zampini   if (mat_ctx->rhs_flip) {
21489566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(pcbddc->original_rhs, standard_rhs, mat_ctx->rhs_flip));
21496cc1294bSstefano_zampini   } else {
21509566063dSJacob Faibussowitsch     PetscCall(VecCopy(standard_rhs, pcbddc->original_rhs));
21516cc1294bSstefano_zampini   }
2152af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
2153229984c5Sstefano_zampini     /* interface pressure rhs */
21549566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->g2g_p, fetidp_flux_rhs, pcbddc->original_rhs, INSERT_VALUES, SCATTER_REVERSE));
21559566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->g2g_p, fetidp_flux_rhs, pcbddc->original_rhs, INSERT_VALUES, SCATTER_REVERSE));
21569566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->g2g_p, standard_rhs, fetidp_flux_rhs, INSERT_VALUES, SCATTER_FORWARD));
21579566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->g2g_p, standard_rhs, fetidp_flux_rhs, INSERT_VALUES, SCATTER_FORWARD));
2158*48a46eb9SPierre Jolivet     if (!mat_ctx->rhs_flip) PetscCall(VecScale(fetidp_flux_rhs, -1.));
21596cc1294bSstefano_zampini   }
2160c08af4c6SStefano Zampini   /*
2161c08af4c6SStefano Zampini      change of basis for physical rhs if needed
2162c08af4c6SStefano Zampini      It also changes the rhs in case of dirichlet boundaries
2163c08af4c6SStefano Zampini   */
21649566063dSJacob Faibussowitsch   PetscCall(PCPreSolve_BDDC(mat_ctx->pc, NULL, pcbddc->original_rhs, NULL));
2165fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
21669566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, pcbddc->original_rhs, pcbddc->work_change));
21673738a8e6SStefano Zampini     work = pcbddc->work_change;
2168fc17d649SStefano Zampini   } else {
21693738a8e6SStefano Zampini     work = pcbddc->original_rhs;
2170fc17d649SStefano Zampini   }
21713425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
21729566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_D, work, mat_ctx->temp_solution_D, INSERT_VALUES, SCATTER_FORWARD));
21739566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_D, work, mat_ctx->temp_solution_D, INSERT_VALUES, SCATTER_FORWARD));
2174fb223d50SStefano Zampini   /* scale rhs since it should be unassembled */
2175fb223d50SStefano Zampini   /* TODO use counter scaling? (also below) */
21769566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD));
21779566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD));
2178674ae819SStefano Zampini   /* Apply partition of unity */
21799566063dSJacob Faibussowitsch   PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B, pcis->D, mat_ctx->temp_solution_B));
21809566063dSJacob Faibussowitsch   /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */
21818eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
21823425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
21839566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0));
21849566063dSJacob Faibussowitsch     PetscCall(KSPSolve(pcbddc->ksp_D, mat_ctx->temp_solution_D, pcis->vec1_D));
21859566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0));
2186c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
21879566063dSJacob Faibussowitsch     PetscCall(MatMult(pcis->A_BI, pcis->vec1_D, pcis->vec1_B));
21889566063dSJacob Faibussowitsch     PetscCall(VecAXPY(mat_ctx->temp_solution_B, -1.0, pcis->vec1_B));
21899566063dSJacob Faibussowitsch     PetscCall(VecSet(work, 0.0));
21909566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, mat_ctx->temp_solution_B, work, ADD_VALUES, SCATTER_REVERSE));
21919566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, mat_ctx->temp_solution_B, work, ADD_VALUES, SCATTER_REVERSE));
21929566063dSJacob Faibussowitsch     /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */
21939566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD));
21949566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD));
21959566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B, pcis->D, mat_ctx->temp_solution_B));
21963425bc38SStefano Zampini   }
21973425bc38SStefano Zampini   /* BDDC rhs */
21989566063dSJacob Faibussowitsch   PetscCall(VecCopy(mat_ctx->temp_solution_B, pcis->vec1_B));
21991baa6e33SBarry Smith   if (pcbddc->switch_static) PetscCall(VecCopy(mat_ctx->temp_solution_D, pcis->vec1_D));
22003425bc38SStefano Zampini   /* apply BDDC */
22019566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n));
22029566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc, PETSC_FALSE));
22039566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n));
2204229984c5Sstefano_zampini 
22053425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
22069566063dSJacob Faibussowitsch   PetscCall(MatMult(mat_ctx->B_delta, pcis->vec1_B, mat_ctx->lambda_local));
22079566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(mat_ctx->l2g_lambda, mat_ctx->lambda_local, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD));
22089566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(mat_ctx->l2g_lambda, mat_ctx->lambda_local, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD));
2209229984c5Sstefano_zampini   /* Add contribution to interface pressures */
2210229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
22119566063dSJacob Faibussowitsch     PetscCall(MatMult(mat_ctx->B_BB, pcis->vec1_B, mat_ctx->vP));
22121baa6e33SBarry Smith     if (pcbddc->switch_static) PetscCall(MatMultAdd(mat_ctx->B_BI, pcis->vec1_D, mat_ctx->vP, mat_ctx->vP));
22139566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->l2g_p, mat_ctx->vP, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD));
22149566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->l2g_p, mat_ctx->vP, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD));
2215229984c5Sstefano_zampini   }
22163425bc38SStefano Zampini   PetscFunctionReturn(0);
22173425bc38SStefano Zampini }
22181e6b0712SBarry Smith 
22193425bc38SStefano Zampini /*@
22200f202f7eSStefano Zampini  PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side
22213425bc38SStefano Zampini 
22223425bc38SStefano Zampini    Collective
22233425bc38SStefano Zampini 
22243425bc38SStefano Zampini    Input Parameters:
22250f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix object obtained by a call to PCBDDCCreateFETIDPOperators
22260f202f7eSStefano Zampini -  standard_rhs    - the right-hand side of the original linear system
22273425bc38SStefano Zampini 
22283425bc38SStefano Zampini    Output Parameters:
22290f202f7eSStefano Zampini .  fetidp_flux_rhs - the right-hand side for the FETI-DP linear system
22303425bc38SStefano Zampini 
22313425bc38SStefano Zampini    Level: developer
22323425bc38SStefano Zampini 
22333425bc38SStefano Zampini    Notes:
22343425bc38SStefano Zampini 
223516b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCCreateFETIDPOperators()`, `PCBDDCMatFETIDPGetSolution()`
22363425bc38SStefano Zampini @*/
22379371c9d4SSatish Balay PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) {
2238674ae819SStefano Zampini   FETIDPMat_ctx mat_ctx;
22393425bc38SStefano Zampini 
22403425bc38SStefano Zampini   PetscFunctionBegin;
2241266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat, MAT_CLASSID, 1);
2242266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_rhs, VEC_CLASSID, 2);
2243266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_rhs, VEC_CLASSID, 3);
22449566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx));
2245cac4c232SBarry Smith   PetscUseMethod(mat_ctx->pc, "PCBDDCMatFETIDPGetRHS_C", (Mat, Vec, Vec), (fetidp_mat, standard_rhs, fetidp_flux_rhs));
22463425bc38SStefano Zampini   PetscFunctionReturn(0);
22473425bc38SStefano Zampini }
22481e6b0712SBarry Smith 
22499371c9d4SSatish Balay static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) {
2250674ae819SStefano Zampini   FETIDPMat_ctx mat_ctx;
22513425bc38SStefano Zampini   PC_IS        *pcis;
22523425bc38SStefano Zampini   PC_BDDC      *pcbddc;
2253229984c5Sstefano_zampini   Vec           work;
22543425bc38SStefano Zampini 
22553425bc38SStefano Zampini   PetscFunctionBegin;
22569566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx));
22573425bc38SStefano Zampini   pcis   = (PC_IS *)mat_ctx->pc->data;
22583425bc38SStefano Zampini   pcbddc = (PC_BDDC *)mat_ctx->pc->data;
22593425bc38SStefano Zampini 
22603425bc38SStefano Zampini   /* apply B_delta^T */
22619566063dSJacob Faibussowitsch   PetscCall(VecSet(pcis->vec1_B, 0.));
22629566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(mat_ctx->l2g_lambda, fetidp_flux_sol, mat_ctx->lambda_local, INSERT_VALUES, SCATTER_REVERSE));
22639566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(mat_ctx->l2g_lambda, fetidp_flux_sol, mat_ctx->lambda_local, INSERT_VALUES, SCATTER_REVERSE));
22649566063dSJacob Faibussowitsch   PetscCall(MatMultTranspose(mat_ctx->B_delta, mat_ctx->lambda_local, pcis->vec1_B));
2265229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
22669566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->l2g_p, fetidp_flux_sol, mat_ctx->vP, INSERT_VALUES, SCATTER_REVERSE));
22679566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->l2g_p, fetidp_flux_sol, mat_ctx->vP, INSERT_VALUES, SCATTER_REVERSE));
22689566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(mat_ctx->Bt_BB, mat_ctx->vP, pcis->vec1_B, pcis->vec1_B));
2269229984c5Sstefano_zampini   }
2270229984c5Sstefano_zampini 
22713425bc38SStefano Zampini   /* compute rhs for BDDC application */
22729566063dSJacob Faibussowitsch   PetscCall(VecAYPX(pcis->vec1_B, -1.0, mat_ctx->temp_solution_B));
22738eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
22749566063dSJacob Faibussowitsch     PetscCall(VecCopy(mat_ctx->temp_solution_D, pcis->vec1_D));
2275229984c5Sstefano_zampini     if (mat_ctx->l2g_p) {
22769566063dSJacob Faibussowitsch       PetscCall(VecScale(mat_ctx->vP, -1.));
22779566063dSJacob Faibussowitsch       PetscCall(MatMultAdd(mat_ctx->Bt_BI, mat_ctx->vP, pcis->vec1_D, pcis->vec1_D));
22783425bc38SStefano Zampini     }
2279229984c5Sstefano_zampini   }
2280229984c5Sstefano_zampini 
22813425bc38SStefano Zampini   /* apply BDDC */
22829566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n));
22839566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc, PETSC_FALSE));
2284229984c5Sstefano_zampini 
2285229984c5Sstefano_zampini   /* put values into global vector */
2286af140850Sstefano_zampini   if (pcbddc->ChangeOfBasisMatrix) work = pcbddc->work_change;
2287af140850Sstefano_zampini   else work = standard_sol;
22889566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, work, INSERT_VALUES, SCATTER_REVERSE));
22899566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, work, INSERT_VALUES, SCATTER_REVERSE));
22908eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
22913425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
22929566063dSJacob Faibussowitsch     PetscCall(MatMult(pcis->A_IB, pcis->vec1_B, pcis->vec1_D));
22939566063dSJacob Faibussowitsch     PetscCall(VecAYPX(pcis->vec1_D, -1.0, mat_ctx->temp_solution_D));
22949566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0));
22959566063dSJacob Faibussowitsch     PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec1_D));
22969566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0));
2297c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
22983425bc38SStefano Zampini   }
2299229984c5Sstefano_zampini 
23009566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_D, work, INSERT_VALUES, SCATTER_REVERSE));
23019566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_D, work, INSERT_VALUES, SCATTER_REVERSE));
2302266e20e9SStefano Zampini   /* add p0 solution to final solution */
23039566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignGetOrSetP0(mat_ctx->pc, work, PETSC_FALSE));
23041baa6e33SBarry Smith   if (pcbddc->ChangeOfBasisMatrix) PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, work, standard_sol));
23059566063dSJacob Faibussowitsch   PetscCall(PCPostSolve_BDDC(mat_ctx->pc, NULL, NULL, standard_sol));
2306af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
23079566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->g2g_p, fetidp_flux_sol, standard_sol, INSERT_VALUES, SCATTER_REVERSE));
23089566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->g2g_p, fetidp_flux_sol, standard_sol, INSERT_VALUES, SCATTER_REVERSE));
2309229984c5Sstefano_zampini   }
23103425bc38SStefano Zampini   PetscFunctionReturn(0);
23113425bc38SStefano Zampini }
23121e6b0712SBarry Smith 
23139371c9d4SSatish Balay static PetscErrorCode PCView_BDDCIPC(PC pc, PetscViewer viewer) {
23145a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
23155a1e936bSStefano Zampini   PetscBool   isascii;
23165a1e936bSStefano Zampini 
23175a1e936bSStefano Zampini   PetscFunctionBegin;
23189566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
23199566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
2320*48a46eb9SPierre Jolivet   if (isascii) PetscCall(PetscViewerASCIIPrintf(viewer, "BDDC interface preconditioner\n"));
23219566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushTab(viewer));
23229566063dSJacob Faibussowitsch   PetscCall(PCView(bddcipc_ctx->bddc, viewer));
23239566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopTab(viewer));
23245a1e936bSStefano Zampini   PetscFunctionReturn(0);
23255a1e936bSStefano Zampini }
23265a1e936bSStefano Zampini 
23279371c9d4SSatish Balay static PetscErrorCode PCSetUp_BDDCIPC(PC pc) {
23285a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
23295a1e936bSStefano Zampini   PetscBool   isbddc;
23305a1e936bSStefano Zampini   Vec         vv;
23315a1e936bSStefano Zampini   IS          is;
23325a1e936bSStefano Zampini   PC_IS      *pcis;
23335a1e936bSStefano Zampini 
23345a1e936bSStefano Zampini   PetscFunctionBegin;
23359566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
23369566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)bddcipc_ctx->bddc, PCBDDC, &isbddc));
233728b400f6SJacob Faibussowitsch   PetscCheck(isbddc, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Invalid type %s. Must be of type bddc", ((PetscObject)bddcipc_ctx->bddc)->type_name);
23389566063dSJacob Faibussowitsch   PetscCall(PCSetUp(bddcipc_ctx->bddc));
23395a1e936bSStefano Zampini 
23405a1e936bSStefano Zampini   /* create interface scatter */
23415a1e936bSStefano Zampini   pcis = (PC_IS *)(bddcipc_ctx->bddc->data);
23429566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l));
23439566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(pc->pmat, &vv, NULL));
23449566063dSJacob Faibussowitsch   PetscCall(ISRenumber(pcis->is_B_global, NULL, NULL, &is));
23459566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(vv, is, pcis->vec1_B, NULL, &bddcipc_ctx->g2l));
23469566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
23479566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&vv));
23485a1e936bSStefano Zampini   PetscFunctionReturn(0);
23495a1e936bSStefano Zampini }
23505a1e936bSStefano Zampini 
23519371c9d4SSatish Balay static PetscErrorCode PCApply_BDDCIPC(PC pc, Vec r, Vec x) {
23525a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
23535a1e936bSStefano Zampini   PC_IS      *pcis;
23545a1e936bSStefano Zampini   VecScatter  tmps;
23555a1e936bSStefano Zampini 
23565a1e936bSStefano Zampini   PetscFunctionBegin;
23579566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
23585a1e936bSStefano Zampini   pcis              = (PC_IS *)(bddcipc_ctx->bddc->data);
23595a1e936bSStefano Zampini   tmps              = pcis->global_to_B;
23605a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
23619566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc, r, pcis->vec1_B));
23629566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc, PETSC_FALSE));
23639566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc, pcis->vec1_B, x));
23645a1e936bSStefano Zampini   pcis->global_to_B = tmps;
23655a1e936bSStefano Zampini   PetscFunctionReturn(0);
23665a1e936bSStefano Zampini }
23675a1e936bSStefano Zampini 
23689371c9d4SSatish Balay static PetscErrorCode PCApplyTranspose_BDDCIPC(PC pc, Vec r, Vec x) {
23695a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
23705a1e936bSStefano Zampini   PC_IS      *pcis;
23715a1e936bSStefano Zampini   VecScatter  tmps;
23725a1e936bSStefano Zampini 
23735a1e936bSStefano Zampini   PetscFunctionBegin;
23749566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
23755a1e936bSStefano Zampini   pcis              = (PC_IS *)(bddcipc_ctx->bddc->data);
23765a1e936bSStefano Zampini   tmps              = pcis->global_to_B;
23775a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
23789566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc, r, pcis->vec1_B));
23799566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc, PETSC_TRUE));
23809566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc, pcis->vec1_B, x));
23815a1e936bSStefano Zampini   pcis->global_to_B = tmps;
23825a1e936bSStefano Zampini   PetscFunctionReturn(0);
23835a1e936bSStefano Zampini }
23845a1e936bSStefano Zampini 
23859371c9d4SSatish Balay static PetscErrorCode PCDestroy_BDDCIPC(PC pc) {
23865a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
23875a1e936bSStefano Zampini 
23885a1e936bSStefano Zampini   PetscFunctionBegin;
23899566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
23909566063dSJacob Faibussowitsch   PetscCall(PCDestroy(&bddcipc_ctx->bddc));
23919566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l));
23929566063dSJacob Faibussowitsch   PetscCall(PetscFree(bddcipc_ctx));
23935a1e936bSStefano Zampini   PetscFunctionReturn(0);
23945a1e936bSStefano Zampini }
23955a1e936bSStefano Zampini 
23963425bc38SStefano Zampini /*@
23970f202f7eSStefano Zampini  PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system
23983425bc38SStefano Zampini 
23993425bc38SStefano Zampini    Collective
24003425bc38SStefano Zampini 
24013425bc38SStefano Zampini    Input Parameters:
24020f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators
24030f202f7eSStefano Zampini -  fetidp_flux_sol - the solution of the FETI-DP linear system
24043425bc38SStefano Zampini 
24053425bc38SStefano Zampini    Output Parameters:
24060f202f7eSStefano Zampini .  standard_sol    - the solution defined on the physical domain
24073425bc38SStefano Zampini 
24083425bc38SStefano Zampini    Level: developer
24093425bc38SStefano Zampini 
24103425bc38SStefano Zampini    Notes:
24113425bc38SStefano Zampini 
241216b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCCreateFETIDPOperators()`, `PCBDDCMatFETIDPGetRHS()`
24133425bc38SStefano Zampini @*/
24149371c9d4SSatish Balay PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) {
2415674ae819SStefano Zampini   FETIDPMat_ctx mat_ctx;
24163425bc38SStefano Zampini 
24173425bc38SStefano Zampini   PetscFunctionBegin;
2418266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat, MAT_CLASSID, 1);
2419266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_sol, VEC_CLASSID, 2);
2420266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_sol, VEC_CLASSID, 3);
24219566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx));
2422cac4c232SBarry Smith   PetscUseMethod(mat_ctx->pc, "PCBDDCMatFETIDPGetSolution_C", (Mat, Vec, Vec), (fetidp_mat, fetidp_flux_sol, standard_sol));
24233425bc38SStefano Zampini   PetscFunctionReturn(0);
24243425bc38SStefano Zampini }
24251e6b0712SBarry Smith 
24269371c9d4SSatish Balay static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc) {
2427674ae819SStefano Zampini   FETIDPMat_ctx fetidpmat_ctx;
24283425bc38SStefano Zampini   Mat           newmat;
2429674ae819SStefano Zampini   FETIDPPC_ctx  fetidppc_ctx;
24303425bc38SStefano Zampini   PC            newpc;
2431ce94432eSBarry Smith   MPI_Comm      comm;
24323425bc38SStefano Zampini 
24333425bc38SStefano Zampini   PetscFunctionBegin;
24349566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)pc, &comm));
243515579a77SStefano Zampini   /* FETI-DP matrix */
24369566063dSJacob Faibussowitsch   PetscCall(PCBDDCCreateFETIDPMatContext(pc, &fetidpmat_ctx));
24371720468bSStefano Zampini   fetidpmat_ctx->fully_redundant = fully_redundant;
24389566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetupFETIDPMatContext(fetidpmat_ctx));
24399566063dSJacob Faibussowitsch   PetscCall(MatCreateShell(comm, fetidpmat_ctx->n, fetidpmat_ctx->n, fetidpmat_ctx->N, fetidpmat_ctx->N, fetidpmat_ctx, &newmat));
24409566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)newmat, !fetidpmat_ctx->l2g_lambda_only ? "F" : "G"));
24419566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(newmat, MATOP_MULT, (void (*)(void))FETIDPMatMult));
24429566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(newmat, MATOP_MULT_TRANSPOSE, (void (*)(void))FETIDPMatMultTranspose));
24439566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(newmat, MATOP_DESTROY, (void (*)(void))PCBDDCDestroyFETIDPMat));
244415579a77SStefano Zampini   /* propagate MatOptions */
244515579a77SStefano Zampini   {
244615579a77SStefano Zampini     PC_BDDC  *pcbddc = (PC_BDDC *)fetidpmat_ctx->pc->data;
2447b94d7dedSBarry Smith     PetscBool isset, issym;
244815579a77SStefano Zampini 
2449b94d7dedSBarry Smith     PetscCall(MatIsSymmetricKnown(pc->mat, &isset, &issym));
2450b94d7dedSBarry Smith     if ((isset && issym) || pcbddc->symmetric_primal) PetscCall(MatSetOption(newmat, MAT_SYMMETRIC, PETSC_TRUE));
245115579a77SStefano Zampini   }
24529566063dSJacob Faibussowitsch   PetscCall(MatSetOptionsPrefix(newmat, prefix));
24539566063dSJacob Faibussowitsch   PetscCall(MatAppendOptionsPrefix(newmat, "fetidp_"));
24549566063dSJacob Faibussowitsch   PetscCall(MatSetUp(newmat));
245515579a77SStefano Zampini   /* FETI-DP preconditioner */
24569566063dSJacob Faibussowitsch   PetscCall(PCBDDCCreateFETIDPPCContext(pc, &fetidppc_ctx));
24579566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetupFETIDPPCContext(newmat, fetidppc_ctx));
24589566063dSJacob Faibussowitsch   PetscCall(PCCreate(comm, &newpc));
24599566063dSJacob Faibussowitsch   PetscCall(PCSetOperators(newpc, newmat, newmat));
24609566063dSJacob Faibussowitsch   PetscCall(PCSetOptionsPrefix(newpc, prefix));
24619566063dSJacob Faibussowitsch   PetscCall(PCAppendOptionsPrefix(newpc, "fetidp_"));
24629566063dSJacob Faibussowitsch   PetscCall(PCSetErrorIfFailure(newpc, pc->erroriffailure));
246315579a77SStefano Zampini   if (!fetidpmat_ctx->l2g_lambda_only) { /* standard FETI-DP */
24649566063dSJacob Faibussowitsch     PetscCall(PCSetType(newpc, PCSHELL));
24659566063dSJacob Faibussowitsch     PetscCall(PCShellSetName(newpc, "FETI-DP multipliers"));
24669566063dSJacob Faibussowitsch     PetscCall(PCShellSetContext(newpc, fetidppc_ctx));
24679566063dSJacob Faibussowitsch     PetscCall(PCShellSetApply(newpc, FETIDPPCApply));
24689566063dSJacob Faibussowitsch     PetscCall(PCShellSetApplyTranspose(newpc, FETIDPPCApplyTranspose));
24699566063dSJacob Faibussowitsch     PetscCall(PCShellSetView(newpc, FETIDPPCView));
24709566063dSJacob Faibussowitsch     PetscCall(PCShellSetDestroy(newpc, PCBDDCDestroyFETIDPPC));
24715a1e936bSStefano Zampini   } else { /* saddle-point FETI-DP */
24725a1e936bSStefano Zampini     Mat       M;
24735a1e936bSStefano Zampini     PetscInt  psize;
24745a1e936bSStefano Zampini     PetscBool fake = PETSC_FALSE, isfieldsplit;
2475e1214c54Sstefano_zampini 
24769566063dSJacob Faibussowitsch     PetscCall(ISViewFromOptions(fetidpmat_ctx->lagrange, NULL, "-lag_view"));
24779566063dSJacob Faibussowitsch     PetscCall(ISViewFromOptions(fetidpmat_ctx->pressure, NULL, "-press_view"));
24789566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_PPmat", (PetscObject *)&M));
24799566063dSJacob Faibussowitsch     PetscCall(PCSetType(newpc, PCFIELDSPLIT));
24809566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetIS(newpc, "lag", fetidpmat_ctx->lagrange));
24819566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetIS(newpc, "p", fetidpmat_ctx->pressure));
24829566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetType(newpc, PC_COMPOSITE_SCHUR));
24839566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetSchurFactType(newpc, PC_FIELDSPLIT_SCHUR_FACT_DIAG));
24849566063dSJacob Faibussowitsch     PetscCall(ISGetSize(fetidpmat_ctx->pressure, &psize));
24855a1e936bSStefano Zampini     if (psize != M->rmap->N) {
24865a1e936bSStefano Zampini       Mat      M2;
24875a1e936bSStefano Zampini       PetscInt lpsize;
24885a1e936bSStefano Zampini 
24895a1e936bSStefano Zampini       fake = PETSC_TRUE;
24909566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(fetidpmat_ctx->pressure, &lpsize));
24919566063dSJacob Faibussowitsch       PetscCall(MatCreate(comm, &M2));
24929566063dSJacob Faibussowitsch       PetscCall(MatSetType(M2, MATAIJ));
24939566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(M2, lpsize, lpsize, psize, psize));
24949566063dSJacob Faibussowitsch       PetscCall(MatSetUp(M2));
24959566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(M2, MAT_FINAL_ASSEMBLY));
24969566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(M2, MAT_FINAL_ASSEMBLY));
24979566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSetSchurPre(newpc, PC_FIELDSPLIT_SCHUR_PRE_USER, M2));
24989566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&M2));
24995a1e936bSStefano Zampini     } else {
25009566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSetSchurPre(newpc, PC_FIELDSPLIT_SCHUR_PRE_USER, M));
25015a1e936bSStefano Zampini     }
25029566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetSchurScale(newpc, 1.0));
250315579a77SStefano Zampini 
250415579a77SStefano Zampini     /* we need to setfromoptions and setup here to access the blocks */
25059566063dSJacob Faibussowitsch     PetscCall(PCSetFromOptions(newpc));
25069566063dSJacob Faibussowitsch     PetscCall(PCSetUp(newpc));
2507e1214c54Sstefano_zampini 
25085a1e936bSStefano Zampini     /* user may have changed the type (e.g. -fetidp_pc_type none) */
25099566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)newpc, PCFIELDSPLIT, &isfieldsplit));
25105a1e936bSStefano Zampini     if (isfieldsplit) {
25115a1e936bSStefano Zampini       KSP      *ksps;
25125a1e936bSStefano Zampini       PC        ppc, lagpc;
25135a1e936bSStefano Zampini       PetscInt  nn;
2514064a4176SStefano Zampini       PetscBool ismatis, matisok = PETSC_FALSE, check = PETSC_FALSE;
25155a1e936bSStefano Zampini 
2516e1214c54Sstefano_zampini       /* set the solver for the (0,0) block */
25179566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSchurGetSubKSP(newpc, &nn, &ksps));
25185a1e936bSStefano Zampini       if (!nn) { /* not of type PC_COMPOSITE_SCHUR */
25199566063dSJacob Faibussowitsch         PetscCall(PCFieldSplitGetSubKSP(newpc, &nn, &ksps));
25205a1e936bSStefano Zampini         if (!fake) { /* pass pmat to the pressure solver */
25215a1e936bSStefano Zampini           Mat F;
25225a1e936bSStefano Zampini 
25239566063dSJacob Faibussowitsch           PetscCall(KSPGetOperators(ksps[1], &F, NULL));
25249566063dSJacob Faibussowitsch           PetscCall(KSPSetOperators(ksps[1], F, M));
25255a1e936bSStefano Zampini         }
25265a1e936bSStefano Zampini       } else {
2527b94d7dedSBarry Smith         PetscBool issym, isset;
25285a1e936bSStefano Zampini         Mat       S;
25295a1e936bSStefano Zampini 
25309566063dSJacob Faibussowitsch         PetscCall(PCFieldSplitSchurGetS(newpc, &S));
2531b94d7dedSBarry Smith         PetscCall(MatIsSymmetricKnown(newmat, &isset, &issym));
2532b94d7dedSBarry Smith         if (isset) PetscCall(MatSetOption(S, MAT_SYMMETRIC, issym));
25335a1e936bSStefano Zampini       }
25349566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksps[0], &lagpc));
25359566063dSJacob Faibussowitsch       PetscCall(PCSetType(lagpc, PCSHELL));
25369566063dSJacob Faibussowitsch       PetscCall(PCShellSetName(lagpc, "FETI-DP multipliers"));
25379566063dSJacob Faibussowitsch       PetscCall(PCShellSetContext(lagpc, fetidppc_ctx));
25389566063dSJacob Faibussowitsch       PetscCall(PCShellSetApply(lagpc, FETIDPPCApply));
25399566063dSJacob Faibussowitsch       PetscCall(PCShellSetApplyTranspose(lagpc, FETIDPPCApplyTranspose));
25409566063dSJacob Faibussowitsch       PetscCall(PCShellSetView(lagpc, FETIDPPCView));
25419566063dSJacob Faibussowitsch       PetscCall(PCShellSetDestroy(lagpc, PCBDDCDestroyFETIDPPC));
25425a1e936bSStefano Zampini 
25435a1e936bSStefano Zampini       /* Olof's idea: interface Schur complement preconditioner for the mass matrix */
25449566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksps[1], &ppc));
25455a1e936bSStefano Zampini       if (fake) {
25465a1e936bSStefano Zampini         BDDCIPC_ctx    bddcipc_ctx;
2547ff11fd76SStefano Zampini         PetscContainer c;
25485a1e936bSStefano Zampini 
25495a1e936bSStefano Zampini         matisok = PETSC_TRUE;
25505a1e936bSStefano Zampini 
25515a1e936bSStefano Zampini         /* create inner BDDC solver */
25529566063dSJacob Faibussowitsch         PetscCall(PetscNew(&bddcipc_ctx));
25539566063dSJacob Faibussowitsch         PetscCall(PCCreate(comm, &bddcipc_ctx->bddc));
25549566063dSJacob Faibussowitsch         PetscCall(PCSetType(bddcipc_ctx->bddc, PCBDDC));
25559566063dSJacob Faibussowitsch         PetscCall(PCSetOperators(bddcipc_ctx->bddc, M, M));
25569566063dSJacob Faibussowitsch         PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_pCSR", (PetscObject *)&c));
25579566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)M, MATIS, &ismatis));
2558ff11fd76SStefano Zampini         if (c && ismatis) {
2559ff11fd76SStefano Zampini           Mat       lM;
2560ff11fd76SStefano Zampini           PetscInt *csr, n;
2561ff11fd76SStefano Zampini 
25629566063dSJacob Faibussowitsch           PetscCall(MatISGetLocalMat(M, &lM));
25639566063dSJacob Faibussowitsch           PetscCall(MatGetSize(lM, &n, NULL));
25649566063dSJacob Faibussowitsch           PetscCall(PetscContainerGetPointer(c, (void **)&csr));
25659566063dSJacob Faibussowitsch           PetscCall(PCBDDCSetLocalAdjacencyGraph(bddcipc_ctx->bddc, n, csr, csr + (n + 1), PETSC_COPY_VALUES));
25669566063dSJacob Faibussowitsch           PetscCall(MatISRestoreLocalMat(M, &lM));
2567ff11fd76SStefano Zampini         }
25689566063dSJacob Faibussowitsch         PetscCall(PCSetOptionsPrefix(bddcipc_ctx->bddc, ((PetscObject)ksps[1])->prefix));
25699566063dSJacob Faibussowitsch         PetscCall(PCSetErrorIfFailure(bddcipc_ctx->bddc, pc->erroriffailure));
25709566063dSJacob Faibussowitsch         PetscCall(PCSetFromOptions(bddcipc_ctx->bddc));
25715a1e936bSStefano Zampini 
25725a1e936bSStefano Zampini         /* wrap the interface application */
25739566063dSJacob Faibussowitsch         PetscCall(PCSetType(ppc, PCSHELL));
25749566063dSJacob Faibussowitsch         PetscCall(PCShellSetName(ppc, "FETI-DP pressure"));
25759566063dSJacob Faibussowitsch         PetscCall(PCShellSetContext(ppc, bddcipc_ctx));
25769566063dSJacob Faibussowitsch         PetscCall(PCShellSetSetUp(ppc, PCSetUp_BDDCIPC));
25779566063dSJacob Faibussowitsch         PetscCall(PCShellSetApply(ppc, PCApply_BDDCIPC));
25789566063dSJacob Faibussowitsch         PetscCall(PCShellSetApplyTranspose(ppc, PCApplyTranspose_BDDCIPC));
25799566063dSJacob Faibussowitsch         PetscCall(PCShellSetView(ppc, PCView_BDDCIPC));
25809566063dSJacob Faibussowitsch         PetscCall(PCShellSetDestroy(ppc, PCDestroy_BDDCIPC));
25815a1e936bSStefano Zampini       }
25825a1e936bSStefano Zampini 
25835a1e936bSStefano Zampini       /* determine if we need to assemble M to construct a preconditioner */
25845a1e936bSStefano Zampini       if (!matisok) {
25859566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)M, MATIS, &ismatis));
25869566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompareAny((PetscObject)ppc, &matisok, PCBDDC, PCJACOBI, PCNONE, PCMG, ""));
2587*48a46eb9SPierre Jolivet         if (ismatis && !matisok) PetscCall(MatConvert(M, MATAIJ, MAT_INPLACE_MATRIX, &M));
25885a1e936bSStefano Zampini       }
2589064a4176SStefano Zampini 
2590064a4176SStefano Zampini       /* run the subproblems to check convergence */
25919566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)newmat)->prefix, "-check_saddlepoint", &check, NULL));
2592064a4176SStefano Zampini       if (check) {
2593064a4176SStefano Zampini         PetscInt i;
2594064a4176SStefano Zampini 
2595064a4176SStefano Zampini         for (i = 0; i < nn; i++) {
2596064a4176SStefano Zampini           KSP       kspC;
2597064a4176SStefano Zampini           PC        pc;
2598064a4176SStefano Zampini           Mat       F, pF;
2599064a4176SStefano Zampini           Vec       x, y;
2600064a4176SStefano Zampini           PetscBool isschur, prec = PETSC_TRUE;
2601064a4176SStefano Zampini 
26029566063dSJacob Faibussowitsch           PetscCall(KSPCreate(PetscObjectComm((PetscObject)ksps[i]), &kspC));
26039566063dSJacob Faibussowitsch           PetscCall(KSPSetOptionsPrefix(kspC, ((PetscObject)ksps[i])->prefix));
26049566063dSJacob Faibussowitsch           PetscCall(KSPAppendOptionsPrefix(kspC, "check_"));
26059566063dSJacob Faibussowitsch           PetscCall(KSPGetOperators(ksps[i], &F, &pF));
26069566063dSJacob Faibussowitsch           PetscCall(PetscObjectTypeCompare((PetscObject)F, MATSCHURCOMPLEMENT, &isschur));
2607064a4176SStefano Zampini           if (isschur) {
2608064a4176SStefano Zampini             KSP  kspS, kspS2;
2609064a4176SStefano Zampini             Mat  A00, pA00, A10, A01, A11;
2610064a4176SStefano Zampini             char prefix[256];
2611064a4176SStefano Zampini 
26129566063dSJacob Faibussowitsch             PetscCall(MatSchurComplementGetKSP(F, &kspS));
26139566063dSJacob Faibussowitsch             PetscCall(MatSchurComplementGetSubMatrices(F, &A00, &pA00, &A01, &A10, &A11));
26149566063dSJacob Faibussowitsch             PetscCall(MatCreateSchurComplement(A00, pA00, A01, A10, A11, &F));
26159566063dSJacob Faibussowitsch             PetscCall(MatSchurComplementGetKSP(F, &kspS2));
26169566063dSJacob Faibussowitsch             PetscCall(PetscSNPrintf(prefix, sizeof(prefix), "%sschur_", ((PetscObject)kspC)->prefix));
26179566063dSJacob Faibussowitsch             PetscCall(KSPSetOptionsPrefix(kspS2, prefix));
26189566063dSJacob Faibussowitsch             PetscCall(KSPGetPC(kspS2, &pc));
26199566063dSJacob Faibussowitsch             PetscCall(PCSetType(pc, PCKSP));
26209566063dSJacob Faibussowitsch             PetscCall(PCKSPSetKSP(pc, kspS));
26219566063dSJacob Faibussowitsch             PetscCall(KSPSetFromOptions(kspS2));
26229566063dSJacob Faibussowitsch             PetscCall(KSPGetPC(kspS2, &pc));
26239566063dSJacob Faibussowitsch             PetscCall(PCSetUseAmat(pc, PETSC_TRUE));
2624064a4176SStefano Zampini           } else {
26259566063dSJacob Faibussowitsch             PetscCall(PetscObjectReference((PetscObject)F));
2626064a4176SStefano Zampini           }
26279566063dSJacob Faibussowitsch           PetscCall(KSPSetFromOptions(kspC));
26289566063dSJacob Faibussowitsch           PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)kspC)->prefix, "-preconditioned", &prec, NULL));
2629064a4176SStefano Zampini           if (prec) {
26309566063dSJacob Faibussowitsch             PetscCall(KSPGetPC(ksps[i], &pc));
26319566063dSJacob Faibussowitsch             PetscCall(KSPSetPC(kspC, pc));
2632064a4176SStefano Zampini           }
26339566063dSJacob Faibussowitsch           PetscCall(KSPSetOperators(kspC, F, pF));
26349566063dSJacob Faibussowitsch           PetscCall(MatCreateVecs(F, &x, &y));
26359566063dSJacob Faibussowitsch           PetscCall(VecSetRandom(x, NULL));
26369566063dSJacob Faibussowitsch           PetscCall(MatMult(F, x, y));
26379566063dSJacob Faibussowitsch           PetscCall(KSPSolve(kspC, y, x));
26389566063dSJacob Faibussowitsch           PetscCall(KSPCheckSolve(kspC, pc, x));
26399566063dSJacob Faibussowitsch           PetscCall(KSPDestroy(&kspC));
26409566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&F));
26419566063dSJacob Faibussowitsch           PetscCall(VecDestroy(&x));
26429566063dSJacob Faibussowitsch           PetscCall(VecDestroy(&y));
2643064a4176SStefano Zampini         }
2644064a4176SStefano Zampini       }
26459566063dSJacob Faibussowitsch       PetscCall(PetscFree(ksps));
2646e1214c54Sstefano_zampini     }
26475a1e936bSStefano Zampini   }
26483425bc38SStefano Zampini   /* return pointers for objects created */
26493425bc38SStefano Zampini   *fetidp_mat = newmat;
26503425bc38SStefano Zampini   *fetidp_pc  = newpc;
26513425bc38SStefano Zampini   PetscFunctionReturn(0);
26523425bc38SStefano Zampini }
26531e6b0712SBarry Smith 
265494ef8ddeSSatish Balay /*@C
26550f202f7eSStefano Zampini  PCBDDCCreateFETIDPOperators - Create FETI-DP operators
26563425bc38SStefano Zampini 
26573425bc38SStefano Zampini    Collective
26583425bc38SStefano Zampini 
26593425bc38SStefano Zampini    Input Parameters:
26601720468bSStefano Zampini +  pc - the BDDC preconditioning context (setup should have been called before)
2661547c9a8eSstefano_zampini .  fully_redundant - true for a fully redundant set of Lagrange multipliers
2662547c9a8eSstefano_zampini -  prefix - optional options database prefix for the objects to be created (can be NULL)
266328509bceSStefano Zampini 
266428509bceSStefano Zampini    Output Parameters:
26650f202f7eSStefano Zampini +  fetidp_mat - shell FETI-DP matrix object
26660f202f7eSStefano Zampini -  fetidp_pc  - shell Dirichlet preconditioner for FETI-DP matrix
266728509bceSStefano Zampini 
26683425bc38SStefano Zampini    Level: developer
26693425bc38SStefano Zampini 
26703425bc38SStefano Zampini    Notes:
26710f202f7eSStefano Zampini      Currently the only operations provided for FETI-DP matrix are MatMult and MatMultTranspose
26723425bc38SStefano Zampini 
267316b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCMatFETIDPGetRHS()`, `PCBDDCMatFETIDPGetSolution()`
26743425bc38SStefano Zampini @*/
26759371c9d4SSatish Balay PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc) {
26763425bc38SStefano Zampini   PetscFunctionBegin;
26773425bc38SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
26783425bc38SStefano Zampini   if (pc->setupcalled) {
2679cac4c232SBarry Smith     PetscUseMethod(pc, "PCBDDCCreateFETIDPOperators_C", (PC, PetscBool, const char *, Mat *, PC *), (pc, fully_redundant, prefix, fetidp_mat, fetidp_pc));
26806080607fSStefano Zampini   } else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "You must call PCSetup_BDDC() first");
26813425bc38SStefano Zampini   PetscFunctionReturn(0);
26823425bc38SStefano Zampini }
26830c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
2684da1bb401SStefano Zampini /*MC
2685da1bb401SStefano Zampini    PCBDDC - Balancing Domain Decomposition by Constraints.
26860c7d97c5SJed Brown 
2687be4a8d98Sprj-    An implementation of the BDDC preconditioner based on the bibliography found below.
268828509bceSStefano Zampini 
268928509bceSStefano Zampini    The matrix to be preconditioned (Pmat) must be of type MATIS.
269028509bceSStefano Zampini 
26910f202f7eSStefano Zampini    Currently works with MATIS matrices with local matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers.
269228509bceSStefano Zampini 
269328509bceSStefano Zampini    It also works with unsymmetric and indefinite problems.
269428509bceSStefano Zampini 
2695b6fdb6dfSStefano Zampini    Unlike 'conventional' interface preconditioners, PCBDDC iterates over all degrees of freedom, not just those on the interface. This allows the use of approximate solvers on the subdomains.
2696b6fdb6dfSStefano Zampini 
2697c7017625SStefano Zampini    Approximate local solvers are automatically adapted (see [1]) if the user has attached a nullspace object to the subdomain matrices, and informed BDDC of using approximate solvers (via the command line).
269828509bceSStefano Zampini 
26990f202f7eSStefano Zampini    Boundary nodes are split in vertices, edges and faces classes using information from the local to global mapping of dofs and the local connectivity graph of nodes. The latter can be customized by using PCBDDCSetLocalAdjacencyGraph()
270030368db7SStefano Zampini    Additional information on dofs can be provided by using PCBDDCSetDofsSplitting(), PCBDDCSetDirichletBoundaries(), PCBDDCSetNeumannBoundaries(), and PCBDDCSetPrimalVerticesIS() and their local counterparts.
270128509bceSStefano Zampini 
27020f202f7eSStefano Zampini    Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). Non-singular modes are retained via SVD.
270328509bceSStefano Zampini 
27040f202f7eSStefano Zampini    Change of basis is performed similarly to [2] when requested. When more than one constraint is present on a single connected component (i.e. an edge or a face), a robust method based on local QR factorizations is used.
27050f202f7eSStefano Zampini    User defined change of basis can be passed to PCBDDC by using PCBDDCSetChangeOfBasisMat()
270628509bceSStefano Zampini 
27070f202f7eSStefano Zampini    The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using a MatPartitioning object.
270828509bceSStefano Zampini 
2709df4d28bfSStefano Zampini    Adaptive selection of primal constraints [4] is supported for SPD systems with high-contrast in the coefficients if MUMPS or MKL_PARDISO are present. Future versions of the code will also consider using PASTIX.
271028509bceSStefano Zampini 
27110f202f7eSStefano Zampini    An experimental interface to the FETI-DP method is available. FETI-DP operators could be created using PCBDDCCreateFETIDPOperators(). A stand-alone class for the FETI-DP method will be provided in the next releases.
27120f202f7eSStefano Zampini 
2713d314f959SVaclav Hapla    Options Database Keys (some of them, run with -help for a complete list):
27140f202f7eSStefano Zampini 
2715a2b725a8SWilliam Gropp +    -pc_bddc_use_vertices <true> - use or not vertices in primal space
27160f202f7eSStefano Zampini .    -pc_bddc_use_edges <true> - use or not edges in primal space
27170f202f7eSStefano Zampini .    -pc_bddc_use_faces <false> - use or not faces in primal space
27180f202f7eSStefano Zampini .    -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems
27190f202f7eSStefano Zampini .    -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only)
27200f202f7eSStefano Zampini .    -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested
27210f202f7eSStefano Zampini .    -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1])
272228509bceSStefano Zampini .    -pc_bddc_levels <0> - maximum number of levels for multilevel
27230f202f7eSStefano 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)
27245459c157SBarry 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)
27250f202f7eSStefano Zampini .    -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling
272671f2caa7Sprj- .    -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)
2727bd2a564bSStefano 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)
272828509bceSStefano Zampini -    -pc_bddc_check_level <0> - set verbosity level of debugging output
272928509bceSStefano Zampini 
273028509bceSStefano Zampini    Options for Dirichlet, Neumann or coarse solver can be set with
273128509bceSStefano Zampini .vb
273228509bceSStefano Zampini       -pc_bddc_dirichlet_
273328509bceSStefano Zampini       -pc_bddc_neumann_
273428509bceSStefano Zampini       -pc_bddc_coarse_
273528509bceSStefano Zampini .ve
2736f9ff08acSPierre Jolivet    e.g. -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. PCBDDC uses by default KSPPREONLY and PCLU.
273728509bceSStefano Zampini 
27380f202f7eSStefano Zampini    When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified as
273928509bceSStefano Zampini .vb
2740312be037SStefano Zampini       -pc_bddc_dirichlet_lN_
2741312be037SStefano Zampini       -pc_bddc_neumann_lN_
2742312be037SStefano Zampini       -pc_bddc_coarse_lN_
274328509bceSStefano Zampini .ve
27440f202f7eSStefano Zampini    Note that level number ranges from the finest (0) to the coarsest (N).
27450f202f7eSStefano Zampini    In order to specify options for the BDDC operators at the coarser levels (and not for the solvers), prepend -pc_bddc_coarse_ or -pc_bddc_coarse_l to the option, e.g.
27460f202f7eSStefano Zampini .vb
27470f202f7eSStefano Zampini      -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3
27480f202f7eSStefano Zampini .ve
27490f202f7eSStefano 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
2750da1bb401SStefano Zampini 
2751be4a8d98Sprj-    References:
2752606c0280SSatish Balay +  * - C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149--168, March 2007
2753606c0280SSatish 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
2754606c0280SSatish Balay .  * - J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", Computing Volume 83, Issue 2--3, pages 55--85, November 2008
2755606c0280SSatish 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
2756be4a8d98Sprj- 
2757da1bb401SStefano Zampini    Level: intermediate
2758da1bb401SStefano Zampini 
2759e94cfbe0SPatrick Sanan    Developer Notes:
2760da1bb401SStefano Zampini 
2761da1bb401SStefano Zampini    Contributed by Stefano Zampini
2762da1bb401SStefano Zampini 
2763db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `MATIS`
2764da1bb401SStefano Zampini M*/
2765b2573a8aSBarry Smith 
27669371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc) {
2767da1bb401SStefano Zampini   PC_BDDC *pcbddc;
2768da1bb401SStefano Zampini 
2769da1bb401SStefano Zampini   PetscFunctionBegin;
27709566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(pc, &pcbddc));
27713ec1f749SStefano Zampini   pc->data = pcbddc;
2772da1bb401SStefano Zampini 
2773da1bb401SStefano Zampini   /* create PCIS data structure */
27749566063dSJacob Faibussowitsch   PetscCall(PCISCreate(pc));
2775da1bb401SStefano Zampini 
27769326c5c6Sstefano_zampini   /* create local graph structure */
27779566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphCreate(&pcbddc->mat_graph));
27789326c5c6Sstefano_zampini 
27799326c5c6Sstefano_zampini   /* BDDC nonzero defaults */
27806d9e27e4SStefano Zampini   pcbddc->use_nnsp                  = PETSC_TRUE;
278108a5cf49SStefano Zampini   pcbddc->use_local_adj             = PETSC_TRUE;
278247d04d0dSStefano Zampini   pcbddc->use_vertices              = PETSC_TRUE;
278347d04d0dSStefano Zampini   pcbddc->use_edges                 = PETSC_TRUE;
27843301b35fSStefano Zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
278514f95afaSStefano Zampini   pcbddc->vertex_size               = 1;
2786c703fcc7SStefano Zampini   pcbddc->recompute_topography      = PETSC_TRUE;
278768457ee5SStefano Zampini   pcbddc->coarse_size               = -1;
278885c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
278947d04d0dSStefano Zampini   pcbddc->coarsening_ratio          = 8;
279057de7509SStefano Zampini   pcbddc->coarse_eqs_per_proc       = 1;
279127b6a85dSStefano Zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
27921e0482f5SStefano Zampini   pcbddc->nedfield                  = -1;
27931e0482f5SStefano Zampini   pcbddc->nedglobal                 = PETSC_TRUE;
2794be12c134Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
2795b96c3477SStefano Zampini   pcbddc->sub_schurs_layers         = -1;
2796bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[0]     = 0.0;
2797bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[1]     = 0.0;
2798b7eb3628SStefano Zampini 
2799da1bb401SStefano Zampini   /* function pointers */
2800da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
280193bd9ae7SStefano Zampini   pc->ops->applytranspose      = PCApplyTranspose_BDDC;
2802da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
2803da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
2804da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
28056b78500eSPatrick Sanan   pc->ops->view                = PCView_BDDC;
28060a545947SLisandro Dalcin   pc->ops->applyrichardson     = NULL;
28070a545947SLisandro Dalcin   pc->ops->applysymmetricleft  = NULL;
28080a545947SLisandro Dalcin   pc->ops->applysymmetricright = NULL;
2809534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
2810534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
28119326c5c6Sstefano_zampini   pc->ops->reset               = PCReset_BDDC;
2812da1bb401SStefano Zampini 
2813da1bb401SStefano Zampini   /* composing function */
28149566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDiscreteGradient_C", PCBDDCSetDiscreteGradient_BDDC));
28159566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDivergenceMat_C", PCBDDCSetDivergenceMat_BDDC));
28169566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetChangeOfBasisMat_C", PCBDDCSetChangeOfBasisMat_BDDC));
28179566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesLocalIS_C", PCBDDCSetPrimalVerticesLocalIS_BDDC));
28189566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesIS_C", PCBDDCSetPrimalVerticesIS_BDDC));
28199566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesLocalIS_C", PCBDDCGetPrimalVerticesLocalIS_BDDC));
28209566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesIS_C", PCBDDCGetPrimalVerticesIS_BDDC));
28219566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetCoarseningRatio_C", PCBDDCSetCoarseningRatio_BDDC));
28229566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevel_C", PCBDDCSetLevel_BDDC));
28239566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetUseExactDirichlet_C", PCBDDCSetUseExactDirichlet_BDDC));
28249566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevels_C", PCBDDCSetLevels_BDDC));
28259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundaries_C", PCBDDCSetDirichletBoundaries_BDDC));
28269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundariesLocal_C", PCBDDCSetDirichletBoundariesLocal_BDDC));
28279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundaries_C", PCBDDCSetNeumannBoundaries_BDDC));
28289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundariesLocal_C", PCBDDCSetNeumannBoundariesLocal_BDDC));
28299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundaries_C", PCBDDCGetDirichletBoundaries_BDDC));
28309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundariesLocal_C", PCBDDCGetDirichletBoundariesLocal_BDDC));
28319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundaries_C", PCBDDCGetNeumannBoundaries_BDDC));
28329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundariesLocal_C", PCBDDCGetNeumannBoundariesLocal_BDDC));
28339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplitting_C", PCBDDCSetDofsSplitting_BDDC));
28349566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplittingLocal_C", PCBDDCSetDofsSplittingLocal_BDDC));
28359566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", PCBDDCSetLocalAdjacencyGraph_BDDC));
28369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCCreateFETIDPOperators_C", PCBDDCCreateFETIDPOperators_BDDC));
28379566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetRHS_C", PCBDDCMatFETIDPGetRHS_BDDC));
28389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetSolution_C", PCBDDCMatFETIDPGetSolution_BDDC));
28399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", PCPreSolveChangeRHS_BDDC));
28409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_BDDC));
2841da1bb401SStefano Zampini   PetscFunctionReturn(0);
2842da1bb401SStefano Zampini }
284343371fb9SStefano Zampini 
284443371fb9SStefano Zampini /*@C
284543371fb9SStefano Zampini  PCBDDCInitializePackage - This function initializes everything in the PCBDDC package. It is called
28468a690491SBarry Smith     from PCInitializePackage().
284743371fb9SStefano Zampini 
284843371fb9SStefano Zampini  Level: developer
284943371fb9SStefano Zampini 
2850db781477SPatrick Sanan  .seealso: `PetscInitialize()`
285143371fb9SStefano Zampini @*/
28529371c9d4SSatish Balay PetscErrorCode PCBDDCInitializePackage(void) {
285343371fb9SStefano Zampini   int i;
285443371fb9SStefano Zampini 
285543371fb9SStefano Zampini   PetscFunctionBegin;
285643371fb9SStefano Zampini   if (PCBDDCPackageInitialized) PetscFunctionReturn(0);
285743371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_TRUE;
28589566063dSJacob Faibussowitsch   PetscCall(PetscRegisterFinalize(PCBDDCFinalizePackage));
285943371fb9SStefano Zampini 
286043371fb9SStefano Zampini   /* general events */
28619566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCTopo", PC_CLASSID, &PC_BDDC_Topology[0]));
28629566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCLKSP", PC_CLASSID, &PC_BDDC_LocalSolvers[0]));
28639566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCLWor", PC_CLASSID, &PC_BDDC_LocalWork[0]));
28649566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCorr", PC_CLASSID, &PC_BDDC_CorrectionSetUp[0]));
28659566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCASet", PC_CLASSID, &PC_BDDC_ApproxSetUp[0]));
28669566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCAApp", PC_CLASSID, &PC_BDDC_ApproxApply[0]));
28679566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCSet", PC_CLASSID, &PC_BDDC_CoarseSetUp[0]));
28689566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCKSP", PC_CLASSID, &PC_BDDC_CoarseSolver[0]));
28699566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCAdap", PC_CLASSID, &PC_BDDC_AdaptiveSetUp[0]));
28709566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCScal", PC_CLASSID, &PC_BDDC_Scaling[0]));
28719566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCSchr", PC_CLASSID, &PC_BDDC_Schurs[0]));
28729566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCDirS", PC_CLASSID, &PC_BDDC_Solves[0][0]));
28739566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCNeuS", PC_CLASSID, &PC_BDDC_Solves[0][1]));
28749566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCoaS", PC_CLASSID, &PC_BDDC_Solves[0][2]));
287543371fb9SStefano Zampini   for (i = 1; i < PETSC_PCBDDC_MAXLEVELS; i++) {
287643371fb9SStefano Zampini     char ename[32];
287743371fb9SStefano Zampini 
28789566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCTopo l%02d", i));
28799566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Topology[i]));
28809566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCLKSP l%02d", i));
28819566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_LocalSolvers[i]));
28829566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCLWor l%02d", i));
28839566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_LocalWork[i]));
28849566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCorr l%02d", i));
28859566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CorrectionSetUp[i]));
28869566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCASet l%02d", i));
28879566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_ApproxSetUp[i]));
28889566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCAApp l%02d", i));
28899566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_ApproxApply[i]));
28909566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCSet l%02d", i));
28919566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CoarseSetUp[i]));
28929566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCKSP l%02d", i));
28939566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CoarseSolver[i]));
28949566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCAdap l%02d", i));
28959566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_AdaptiveSetUp[i]));
28969566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCScal l%02d", i));
28979566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Scaling[i]));
28989566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCSchr l%02d", i));
28999566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Schurs[i]));
29009566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCDirS l%02d", i));
29019566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][0]));
29029566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCNeuS l%02d", i));
29039566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][1]));
29049566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCoaS l%02d", i));
29059566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][2]));
290643371fb9SStefano Zampini   }
290743371fb9SStefano Zampini   PetscFunctionReturn(0);
290843371fb9SStefano Zampini }
290943371fb9SStefano Zampini 
291043371fb9SStefano Zampini /*@C
291143371fb9SStefano Zampini  PCBDDCFinalizePackage - This function frees everything from the PCBDDC package. It is
291243371fb9SStefano Zampini     called from PetscFinalize() automatically.
291343371fb9SStefano Zampini 
291443371fb9SStefano Zampini  Level: developer
291543371fb9SStefano Zampini 
2916db781477SPatrick Sanan  .seealso: `PetscFinalize()`
291743371fb9SStefano Zampini @*/
29189371c9d4SSatish Balay PetscErrorCode PCBDDCFinalizePackage(void) {
291943371fb9SStefano Zampini   PetscFunctionBegin;
292043371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_FALSE;
292143371fb9SStefano Zampini   PetscFunctionReturn(0);
292243371fb9SStefano Zampini }
2923