xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision f1580f4e3ce5d5b2393648fd039d0d41b440385d)
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));
92ad540459SPierre Jolivet   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 
14748a46eb9SPierre 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     }
15648a46eb9SPierre 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]));
23148a46eb9SPierre 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 
297*f1580f4eSBarry Smith    Collective on pc
298a13144ffSStefano Zampini 
299a13144ffSStefano Zampini    Input Parameters:
300a13144ffSStefano Zampini +  pc         - the preconditioning context
301*f1580f4eSBarry Smith .  G          - the discrete gradient matrix (in `MATAIJ` 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 
309*f1580f4eSBarry Smith    Note:
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 
317*f1580f4eSBarry Smith .seealso: `PCBDDC`, `PCBDDCSetDofsSplitting()`, `PCBDDCSetDofsSplittingLocal()`, `MATAIJ`, `PCBDDCSetDivergenceMat()`
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 
352*f1580f4eSBarry Smith    Collective on pc
353a198735bSStefano Zampini 
354a198735bSStefano Zampini    Input Parameters:
355a198735bSStefano Zampini +  pc - the preconditioning context
356*f1580f4eSBarry Smith .  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.
358*f1580f4eSBarry Smith -  vl2l - optional index set describing the local (wrt the local matrix in divudotp) to local (wrt the local matrix
359*f1580f4eSBarry Smith    in the preconditioning matrix) map for the velocities
360a198735bSStefano Zampini 
361a198735bSStefano Zampini    Level: advanced
362a198735bSStefano Zampini 
36395452b02SPatrick Sanan    Notes:
36495452b02SPatrick Sanan    This auxiliary matrix is used to compute quadrature weights representing the net-flux across subdomain boundaries
365*f1580f4eSBarry Smith 
36605a3bf82SStefano Zampini    If vl2l is NULL, the local ordering for velocities in divudotp should match that of the preconditioning matrix
367a198735bSStefano Zampini 
368*f1580f4eSBarry Smith .seealso: `PCBDDC`, `PCBDDCSetDiscreteGradient()`
369a198735bSStefano Zampini @*/
3709371c9d4SSatish Balay PetscErrorCode PCBDDCSetDivergenceMat(PC pc, Mat divudotp, PetscBool trans, IS vl2l) {
371a198735bSStefano Zampini   PetscBool ismatis;
372a198735bSStefano Zampini 
373a198735bSStefano Zampini   PetscFunctionBegin;
374a198735bSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
375a198735bSStefano Zampini   PetscValidHeaderSpecific(divudotp, MAT_CLASSID, 2);
376a198735bSStefano Zampini   PetscCheckSameComm(pc, 1, divudotp, 2);
3778ae0ca82SStefano Zampini   PetscValidLogicalCollectiveBool(pc, trans, 3);
3781b24a7afSStefano Zampini   if (vl2l) PetscValidHeaderSpecific(vl2l, IS_CLASSID, 4);
3799566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)divudotp, MATIS, &ismatis));
38028b400f6SJacob Faibussowitsch   PetscCheck(ismatis, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Divergence matrix needs to be of type MATIS");
381cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDivergenceMat_C", (PC, Mat, PetscBool, IS), (pc, divudotp, trans, vl2l));
382a198735bSStefano Zampini   PetscFunctionReturn(0);
383a198735bSStefano Zampini }
3842d505d7fSStefano Zampini 
3859371c9d4SSatish Balay static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change, PetscBool interior) {
386b9b85e73SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
387b9b85e73SStefano Zampini 
388b9b85e73SStefano Zampini   PetscFunctionBegin;
3899566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)change));
3909566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->user_ChangeOfBasisMatrix));
391b9b85e73SStefano Zampini   pcbddc->user_ChangeOfBasisMatrix = change;
3921dd7afcfSStefano Zampini   pcbddc->change_interior          = interior;
393b9b85e73SStefano Zampini   PetscFunctionReturn(0);
394b9b85e73SStefano Zampini }
39532fe681dSStefano Zampini 
396b9b85e73SStefano Zampini /*@
397906d46d4SStefano Zampini  PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs
398b9b85e73SStefano Zampini 
399*f1580f4eSBarry Smith    Collective on pc
400b9b85e73SStefano Zampini 
401b9b85e73SStefano Zampini    Input Parameters:
402b9b85e73SStefano Zampini +  pc - the preconditioning context
4031dd7afcfSStefano Zampini .  change - the change of basis matrix
4041dd7afcfSStefano Zampini -  interior - whether or not the change of basis modifies interior dofs
405b9b85e73SStefano Zampini 
406b9b85e73SStefano Zampini    Level: intermediate
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));
43648a46eb9SPierre 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 /*@
445*f1580f4eSBarry Smith  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 
455*f1580f4eSBarry Smith    Note:
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 /*@
478*f1580f4eSBarry Smith  PCBDDCGetPrimalVerticesIS - Get user defined primal vertices set with `PCBDDCSetPrimalVerticesIS()`
4793100ebe3SStefano Zampini 
4803100ebe3SStefano Zampini    Collective
4813100ebe3SStefano Zampini 
482*f1580f4eSBarry Smith    Input Parameter:
4833100ebe3SStefano Zampini .  pc - the preconditioning context
4843100ebe3SStefano Zampini 
485*f1580f4eSBarry Smith    Output Parameter:
4863100ebe3SStefano Zampini .  is - index set of primal vertices in global numbering (NULL if not set)
4873100ebe3SStefano Zampini 
4883100ebe3SStefano Zampini    Level: intermediate
4893100ebe3SStefano Zampini 
490db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`, `PCBDDCGetPrimalVerticesLocalIS()`
4913100ebe3SStefano Zampini @*/
4929371c9d4SSatish Balay PetscErrorCode PCBDDCGetPrimalVerticesIS(PC pc, IS *is) {
4933100ebe3SStefano Zampini   PetscFunctionBegin;
4943100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
4953100ebe3SStefano Zampini   PetscValidPointer(is, 2);
496cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetPrimalVerticesIS_C", (PC, IS *), (pc, is));
4973100ebe3SStefano Zampini   PetscFunctionReturn(0);
4983100ebe3SStefano Zampini }
4993100ebe3SStefano Zampini 
5009371c9d4SSatish Balay static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices) {
501674ae819SStefano Zampini   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
50256282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
5031e6b0712SBarry Smith 
504674ae819SStefano Zampini   PetscFunctionBegin;
5059566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)PrimalVertices));
50648a46eb9SPierre Jolivet   if (pcbddc->user_primal_vertices_local) PetscCall(ISEqual(PrimalVertices, pcbddc->user_primal_vertices_local, &isequal));
5079566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices));
5089566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local));
50930368db7SStefano Zampini   pcbddc->user_primal_vertices_local = PrimalVertices;
51056282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
511674ae819SStefano Zampini   PetscFunctionReturn(0);
512674ae819SStefano Zampini }
5133100ebe3SStefano Zampini 
514674ae819SStefano Zampini /*@
515*f1580f4eSBarry Smith  PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in `PCBDDC`
516674ae819SStefano Zampini 
51717eb1463SStefano Zampini    Collective
518674ae819SStefano Zampini 
519674ae819SStefano Zampini    Input Parameters:
520674ae819SStefano Zampini +  pc - the preconditioning context
52117eb1463SStefano Zampini -  PrimalVertices - index set of primal vertices in local numbering (can be empty)
522674ae819SStefano Zampini 
523674ae819SStefano Zampini    Level: intermediate
524674ae819SStefano Zampini 
525db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesLocalIS()`
526674ae819SStefano Zampini @*/
5279371c9d4SSatish Balay PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices) {
528674ae819SStefano Zampini   PetscFunctionBegin;
529674ae819SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
530674ae819SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices, IS_CLASSID, 2);
53117eb1463SStefano Zampini   PetscCheckSameComm(pc, 1, PrimalVertices, 2);
532cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetPrimalVerticesLocalIS_C", (PC, IS), (pc, PrimalVertices));
533674ae819SStefano Zampini   PetscFunctionReturn(0);
534674ae819SStefano Zampini }
5352d505d7fSStefano Zampini 
5369371c9d4SSatish Balay static PetscErrorCode PCBDDCGetPrimalVerticesLocalIS_BDDC(PC pc, IS *is) {
5373100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
5383100ebe3SStefano Zampini 
5393100ebe3SStefano Zampini   PetscFunctionBegin;
5403100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices_local;
5413100ebe3SStefano Zampini   PetscFunctionReturn(0);
5423100ebe3SStefano Zampini }
5433100ebe3SStefano Zampini 
5443100ebe3SStefano Zampini /*@
545*f1580f4eSBarry Smith  PCBDDCGetPrimalVerticesLocalIS - Get user defined primal vertices set with `PCBDDCSetPrimalVerticesLocalIS()`
5463100ebe3SStefano Zampini 
5473100ebe3SStefano Zampini    Collective
5483100ebe3SStefano Zampini 
549*f1580f4eSBarry Smith    Input Parameter:
5503100ebe3SStefano Zampini .  pc - the preconditioning context
5513100ebe3SStefano Zampini 
552*f1580f4eSBarry Smith    Output Parameter:
5533100ebe3SStefano Zampini .  is - index set of primal vertices in local numbering (NULL if not set)
5543100ebe3SStefano Zampini 
5553100ebe3SStefano Zampini    Level: intermediate
5563100ebe3SStefano Zampini 
557db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`
5583100ebe3SStefano Zampini @*/
5599371c9d4SSatish Balay PetscErrorCode PCBDDCGetPrimalVerticesLocalIS(PC pc, IS *is) {
5603100ebe3SStefano Zampini   PetscFunctionBegin;
5613100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
5623100ebe3SStefano Zampini   PetscValidPointer(is, 2);
563cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetPrimalVerticesLocalIS_C", (PC, IS *), (pc, is));
5643100ebe3SStefano Zampini   PetscFunctionReturn(0);
5653100ebe3SStefano Zampini }
5663100ebe3SStefano Zampini 
5679371c9d4SSatish Balay static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc, PetscInt k) {
5684fad6a16SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
5694fad6a16SStefano Zampini 
5704fad6a16SStefano Zampini   PetscFunctionBegin;
5714fad6a16SStefano Zampini   pcbddc->coarsening_ratio = k;
5724fad6a16SStefano Zampini   PetscFunctionReturn(0);
5734fad6a16SStefano Zampini }
5741e6b0712SBarry Smith 
5754fad6a16SStefano Zampini /*@
576*f1580f4eSBarry Smith   PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel version
5774fad6a16SStefano Zampini 
578*f1580f4eSBarry Smith    Logically collective on pc
5794fad6a16SStefano Zampini 
5804fad6a16SStefano Zampini    Input Parameters:
5814fad6a16SStefano Zampini +  pc - the preconditioning context
58228509bceSStefano Zampini -  k - coarsening ratio (H/h at the coarser level)
5834fad6a16SStefano Zampini 
584*f1580f4eSBarry Smith    Options Database Key:
58567b8a455SSatish Balay .    -pc_bddc_coarsening_ratio <int> - Set coarsening ratio used in multilevel coarsening
5864fad6a16SStefano Zampini 
5874fad6a16SStefano Zampini    Level: intermediate
5884fad6a16SStefano Zampini 
589*f1580f4eSBarry Smith    Note:
5900f202f7eSStefano Zampini    Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level
5914fad6a16SStefano Zampini 
592db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetLevels()`
5934fad6a16SStefano Zampini @*/
5949371c9d4SSatish Balay PetscErrorCode PCBDDCSetCoarseningRatio(PC pc, PetscInt k) {
5954fad6a16SStefano Zampini   PetscFunctionBegin;
5964fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
5972b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc, k, 2);
598cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetCoarseningRatio_C", (PC, PetscInt), (pc, k));
5994fad6a16SStefano Zampini   PetscFunctionReturn(0);
6004fad6a16SStefano Zampini }
6012b510759SStefano Zampini 
602b8ffe317SStefano Zampini /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */
6039371c9d4SSatish Balay static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc, PetscBool flg) {
604b8ffe317SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
605b8ffe317SStefano Zampini 
606b8ffe317SStefano Zampini   PetscFunctionBegin;
60785c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = flg;
608b8ffe317SStefano Zampini   PetscFunctionReturn(0);
609b8ffe317SStefano Zampini }
610b8ffe317SStefano Zampini 
6119371c9d4SSatish Balay PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc, PetscBool flg) {
6122b510759SStefano Zampini   PetscFunctionBegin;
6132b510759SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
614b8ffe317SStefano Zampini   PetscValidLogicalCollectiveBool(pc, flg, 2);
615cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetUseExactDirichlet_C", (PC, PetscBool), (pc, flg));
6162b510759SStefano Zampini   PetscFunctionReturn(0);
6172b510759SStefano Zampini }
6181e6b0712SBarry Smith 
6199371c9d4SSatish Balay static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc, PetscInt level) {
6204fad6a16SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
6214fad6a16SStefano Zampini 
6224fad6a16SStefano Zampini   PetscFunctionBegin;
6232b510759SStefano Zampini   pcbddc->current_level = level;
6244fad6a16SStefano Zampini   PetscFunctionReturn(0);
6254fad6a16SStefano Zampini }
6261e6b0712SBarry Smith 
6279371c9d4SSatish Balay PetscErrorCode PCBDDCSetLevel(PC pc, PetscInt level) {
628b8ffe317SStefano Zampini   PetscFunctionBegin;
629b8ffe317SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
630b8ffe317SStefano Zampini   PetscValidLogicalCollectiveInt(pc, level, 2);
631cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetLevel_C", (PC, PetscInt), (pc, level));
632b8ffe317SStefano Zampini   PetscFunctionReturn(0);
633b8ffe317SStefano Zampini }
634b8ffe317SStefano Zampini 
6359371c9d4SSatish Balay static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc, PetscInt levels) {
6362b510759SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
6372b510759SStefano Zampini 
6382b510759SStefano Zampini   PetscFunctionBegin;
6397827d75bSBarry 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);
6402b510759SStefano Zampini   pcbddc->max_levels = levels;
6412b510759SStefano Zampini   PetscFunctionReturn(0);
6422b510759SStefano Zampini }
6432b510759SStefano Zampini 
6444fad6a16SStefano Zampini /*@
645*f1580f4eSBarry Smith  PCBDDCSetLevels - Sets the maximum number of additional levels allowed for multilevel `PCBDDC`
6464fad6a16SStefano Zampini 
647*f1580f4eSBarry Smith    Logically collective on pc
6484fad6a16SStefano Zampini 
6494fad6a16SStefano Zampini    Input Parameters:
6504fad6a16SStefano Zampini +  pc - the preconditioning context
65137ebbdf7SStefano Zampini -  levels - the maximum number of levels
6524fad6a16SStefano Zampini 
653*f1580f4eSBarry Smith    Options Database Key:
65467b8a455SSatish Balay .    -pc_bddc_levels <int> - Set maximum number of levels for multilevel
6554fad6a16SStefano Zampini 
6564fad6a16SStefano Zampini    Level: intermediate
6574fad6a16SStefano Zampini 
658*f1580f4eSBarry Smith    Note:
65937ebbdf7SStefano Zampini    The default value is 0, that gives the classical two-levels BDDC
6604fad6a16SStefano Zampini 
661db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetCoarseningRatio()`
6624fad6a16SStefano Zampini @*/
6639371c9d4SSatish Balay PetscErrorCode PCBDDCSetLevels(PC pc, PetscInt levels) {
6644fad6a16SStefano Zampini   PetscFunctionBegin;
6654fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
6662b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc, levels, 2);
667cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetLevels_C", (PC, PetscInt), (pc, levels));
6684fad6a16SStefano Zampini   PetscFunctionReturn(0);
6694fad6a16SStefano Zampini }
6701e6b0712SBarry Smith 
6719371c9d4SSatish Balay static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc, IS DirichletBoundaries) {
6723b03a366Sstefano_zampini   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
67356282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
6743b03a366Sstefano_zampini 
6753b03a366Sstefano_zampini   PetscFunctionBegin;
6769566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)DirichletBoundaries));
67748a46eb9SPierre Jolivet   if (pcbddc->DirichletBoundaries) PetscCall(ISEqual(DirichletBoundaries, pcbddc->DirichletBoundaries, &isequal));
678a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
6799566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal));
6809566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundaries));
68136e030ebSStefano Zampini   pcbddc->DirichletBoundaries = DirichletBoundaries;
68256282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
6833b03a366Sstefano_zampini   PetscFunctionReturn(0);
6843b03a366Sstefano_zampini }
6851e6b0712SBarry Smith 
6863b03a366Sstefano_zampini /*@
68728509bceSStefano Zampini  PCBDDCSetDirichletBoundaries - Set IS defining Dirichlet boundaries for the global problem.
6883b03a366Sstefano_zampini 
689785d1243SStefano Zampini    Collective
6903b03a366Sstefano_zampini 
6913b03a366Sstefano_zampini    Input Parameters:
6923b03a366Sstefano_zampini +  pc - the preconditioning context
693785d1243SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries
6943b03a366Sstefano_zampini 
6953b03a366Sstefano_zampini    Level: intermediate
6963b03a366Sstefano_zampini 
697*f1580f4eSBarry Smith    Note:
698*f1580f4eSBarry Smith    Provide the information if you used `MatZeroRows()` or `MatZeroRowsColumns()`. Any process can list any global node
6993b03a366Sstefano_zampini 
700db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetDirichletBoundariesLocal()`, `MatZeroRows()`, `MatZeroRowsColumns()`
7013b03a366Sstefano_zampini @*/
7029371c9d4SSatish Balay PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc, IS DirichletBoundaries) {
7033b03a366Sstefano_zampini   PetscFunctionBegin;
7043b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
705674ae819SStefano Zampini   PetscValidHeaderSpecific(DirichletBoundaries, IS_CLASSID, 2);
706785d1243SStefano Zampini   PetscCheckSameComm(pc, 1, DirichletBoundaries, 2);
707cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDirichletBoundaries_C", (PC, IS), (pc, DirichletBoundaries));
7083b03a366Sstefano_zampini   PetscFunctionReturn(0);
7093b03a366Sstefano_zampini }
7101e6b0712SBarry Smith 
7119371c9d4SSatish Balay static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc, IS DirichletBoundaries) {
7123b03a366Sstefano_zampini   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
71356282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
7143b03a366Sstefano_zampini 
7153b03a366Sstefano_zampini   PetscFunctionBegin;
7169566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)DirichletBoundaries));
71748a46eb9SPierre Jolivet   if (pcbddc->DirichletBoundariesLocal) PetscCall(ISEqual(DirichletBoundaries, pcbddc->DirichletBoundariesLocal, &isequal));
718a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
7199566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal));
7209566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundaries));
721785d1243SStefano Zampini   pcbddc->DirichletBoundariesLocal = DirichletBoundaries;
72256282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7233b03a366Sstefano_zampini   PetscFunctionReturn(0);
7243b03a366Sstefano_zampini }
7253b03a366Sstefano_zampini 
7263b03a366Sstefano_zampini /*@
72782ba6b80SStefano Zampini  PCBDDCSetDirichletBoundariesLocal - Set IS defining Dirichlet boundaries for the global problem in local ordering.
7283b03a366Sstefano_zampini 
729785d1243SStefano Zampini    Collective
7303b03a366Sstefano_zampini 
7313b03a366Sstefano_zampini    Input Parameters:
7323b03a366Sstefano_zampini +  pc - the preconditioning context
73382ba6b80SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries (in local ordering)
7343b03a366Sstefano_zampini 
7353b03a366Sstefano_zampini    Level: intermediate
7363b03a366Sstefano_zampini 
737db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetDirichletBoundaries()`, `MatZeroRows()`, `MatZeroRowsColumns()`
7383b03a366Sstefano_zampini @*/
7399371c9d4SSatish Balay PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc, IS DirichletBoundaries) {
7403b03a366Sstefano_zampini   PetscFunctionBegin;
7413b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
7423b03a366Sstefano_zampini   PetscValidHeaderSpecific(DirichletBoundaries, IS_CLASSID, 2);
74382ba6b80SStefano Zampini   PetscCheckSameComm(pc, 1, DirichletBoundaries, 2);
744cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDirichletBoundariesLocal_C", (PC, IS), (pc, DirichletBoundaries));
7453b03a366Sstefano_zampini   PetscFunctionReturn(0);
7463b03a366Sstefano_zampini }
7473b03a366Sstefano_zampini 
7489371c9d4SSatish Balay static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc, IS NeumannBoundaries) {
7490c7d97c5SJed Brown   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
75056282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
7510c7d97c5SJed Brown 
7520c7d97c5SJed Brown   PetscFunctionBegin;
7539566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries));
75448a46eb9SPierre Jolivet   if (pcbddc->NeumannBoundaries) PetscCall(ISEqual(NeumannBoundaries, pcbddc->NeumannBoundaries, &isequal));
755a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
7569566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal));
7579566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundaries));
75836e030ebSStefano Zampini   pcbddc->NeumannBoundaries = NeumannBoundaries;
75956282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7600c7d97c5SJed Brown   PetscFunctionReturn(0);
7610c7d97c5SJed Brown }
7621e6b0712SBarry Smith 
76357527edcSJed Brown /*@
764*f1580f4eSBarry Smith    PCBDDCSetNeumannBoundaries - Set `IS` defining Neumann boundaries for the global problem.
76557527edcSJed Brown 
766*f1580f4eSBarry Smith    Collective on pc
76757527edcSJed Brown 
76857527edcSJed Brown    Input Parameters:
76957527edcSJed Brown +  pc - the preconditioning context
770785d1243SStefano Zampini -  NeumannBoundaries - parallel IS defining the Neumann boundaries
77157527edcSJed Brown 
77257527edcSJed Brown    Level: intermediate
77357527edcSJed Brown 
774*f1580f4eSBarry Smith    Note:
7750f202f7eSStefano Zampini    Any process can list any global node
77657527edcSJed Brown 
777db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetNeumannBoundariesLocal()`
77857527edcSJed Brown @*/
7799371c9d4SSatish Balay PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc, IS NeumannBoundaries) {
7800c7d97c5SJed Brown   PetscFunctionBegin;
7810c7d97c5SJed Brown   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
782674ae819SStefano Zampini   PetscValidHeaderSpecific(NeumannBoundaries, IS_CLASSID, 2);
783785d1243SStefano Zampini   PetscCheckSameComm(pc, 1, NeumannBoundaries, 2);
784cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetNeumannBoundaries_C", (PC, IS), (pc, NeumannBoundaries));
78553cdbc3dSStefano Zampini   PetscFunctionReturn(0);
78653cdbc3dSStefano Zampini }
7871e6b0712SBarry Smith 
7889371c9d4SSatish Balay static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc, IS NeumannBoundaries) {
7890c7d97c5SJed Brown   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
79056282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
7910c7d97c5SJed Brown 
7920c7d97c5SJed Brown   PetscFunctionBegin;
7939566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries));
79448a46eb9SPierre Jolivet   if (pcbddc->NeumannBoundariesLocal) PetscCall(ISEqual(NeumannBoundaries, pcbddc->NeumannBoundariesLocal, &isequal));
795a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
7969566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal));
7979566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundaries));
798785d1243SStefano Zampini   pcbddc->NeumannBoundariesLocal = NeumannBoundaries;
79956282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
8000c7d97c5SJed Brown   PetscFunctionReturn(0);
8010c7d97c5SJed Brown }
8020c7d97c5SJed Brown 
8030c7d97c5SJed Brown /*@
80482ba6b80SStefano Zampini  PCBDDCSetNeumannBoundariesLocal - Set IS defining Neumann boundaries for the global problem in local ordering.
8050c7d97c5SJed Brown 
806785d1243SStefano Zampini    Collective
8070c7d97c5SJed Brown 
8080c7d97c5SJed Brown    Input Parameters:
8090c7d97c5SJed Brown +  pc - the preconditioning context
81082ba6b80SStefano Zampini -  NeumannBoundaries - parallel IS defining the subdomain part of Neumann boundaries (in local ordering)
8110c7d97c5SJed Brown 
8120c7d97c5SJed Brown    Level: intermediate
8130c7d97c5SJed Brown 
814*f1580f4eSBarry Smith .seealso: `PCBDDC`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCGetDirichletBoundaries()`
8150c7d97c5SJed Brown @*/
8169371c9d4SSatish Balay PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc, IS NeumannBoundaries) {
8170c7d97c5SJed Brown   PetscFunctionBegin;
8180c7d97c5SJed Brown   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
8190c7d97c5SJed Brown   PetscValidHeaderSpecific(NeumannBoundaries, IS_CLASSID, 2);
82082ba6b80SStefano Zampini   PetscCheckSameComm(pc, 1, NeumannBoundaries, 2);
821cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetNeumannBoundariesLocal_C", (PC, IS), (pc, NeumannBoundaries));
82253cdbc3dSStefano Zampini   PetscFunctionReturn(0);
82353cdbc3dSStefano Zampini }
82453cdbc3dSStefano Zampini 
8259371c9d4SSatish Balay static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc, IS *DirichletBoundaries) {
826da1bb401SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
827da1bb401SStefano Zampini 
828da1bb401SStefano Zampini   PetscFunctionBegin;
829da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
830da1bb401SStefano Zampini   PetscFunctionReturn(0);
831da1bb401SStefano Zampini }
8321e6b0712SBarry Smith 
833da1bb401SStefano Zampini /*@
834*f1580f4eSBarry Smith    PCBDDCGetDirichletBoundaries - Get parallel `IS` for Dirichlet boundaries
835da1bb401SStefano Zampini 
836785d1243SStefano Zampini    Collective
837785d1243SStefano Zampini 
838*f1580f4eSBarry Smith    Input Parameter:
839785d1243SStefano Zampini .  pc - the preconditioning context
840785d1243SStefano Zampini 
841*f1580f4eSBarry Smith    Output Parameter:
842785d1243SStefano Zampini .  DirichletBoundaries - index set defining the Dirichlet boundaries
843785d1243SStefano Zampini 
844785d1243SStefano Zampini    Level: intermediate
845785d1243SStefano Zampini 
846*f1580f4eSBarry Smith    Note:
847*f1580f4eSBarry Smith    The `IS` returned (if any) is the same passed in earlier by the user with `PCBDDCSetDirichletBoundaries()`
848785d1243SStefano Zampini 
849*f1580f4eSBarry Smith .seealso: `PCBDDC`, `PCBDDCSetDirichletBoundaries()`
850785d1243SStefano Zampini @*/
8519371c9d4SSatish Balay PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc, IS *DirichletBoundaries) {
852785d1243SStefano Zampini   PetscFunctionBegin;
853785d1243SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
854cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetDirichletBoundaries_C", (PC, IS *), (pc, DirichletBoundaries));
855785d1243SStefano Zampini   PetscFunctionReturn(0);
856785d1243SStefano Zampini }
857785d1243SStefano Zampini 
8589371c9d4SSatish Balay static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc, IS *DirichletBoundaries) {
859785d1243SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
860785d1243SStefano Zampini 
861785d1243SStefano Zampini   PetscFunctionBegin;
862785d1243SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundariesLocal;
863785d1243SStefano Zampini   PetscFunctionReturn(0);
864785d1243SStefano Zampini }
865785d1243SStefano Zampini 
866da1bb401SStefano Zampini /*@
867*f1580f4eSBarry Smith    PCBDDCGetDirichletBoundariesLocal - Get parallel `IS` for Dirichlet boundaries (in local ordering)
868da1bb401SStefano Zampini 
869785d1243SStefano Zampini    Collective
870da1bb401SStefano Zampini 
871*f1580f4eSBarry Smith    Input Parameter:
87228509bceSStefano Zampini .  pc - the preconditioning context
873da1bb401SStefano Zampini 
874*f1580f4eSBarry Smith    Output Parameter:
87528509bceSStefano Zampini .  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
876da1bb401SStefano Zampini 
877da1bb401SStefano Zampini    Level: intermediate
878da1bb401SStefano Zampini 
879*f1580f4eSBarry Smith    Note:
880*f1580f4eSBarry Smith    The `IS` returned could be the same passed in earlier by the user (if provided with `PCBDDCSetDirichletBoundariesLocal()`)
881*f1580f4eSBarry Smith    or a global-to-local map of the global `IS` (if provided with `PCBDDCSetDirichletBoundaries()`).
882*f1580f4eSBarry Smith    In the latter case, the `IS` will be available only after `PCSetUp()`.
883da1bb401SStefano Zampini 
884*f1580f4eSBarry Smith .seealso: `PCBDDC`, `PCBDDCGetDirichletBoundariesLocal()`, `PCBDDCGetDirichletBoundaries()`, `PCBDDCSetDirichletBoundaries()`
885da1bb401SStefano Zampini @*/
8869371c9d4SSatish Balay PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc, IS *DirichletBoundaries) {
887da1bb401SStefano Zampini   PetscFunctionBegin;
888da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
889cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetDirichletBoundariesLocal_C", (PC, IS *), (pc, DirichletBoundaries));
890da1bb401SStefano Zampini   PetscFunctionReturn(0);
891da1bb401SStefano Zampini }
8921e6b0712SBarry Smith 
8939371c9d4SSatish Balay static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc, IS *NeumannBoundaries) {
89453cdbc3dSStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
89553cdbc3dSStefano Zampini 
89653cdbc3dSStefano Zampini   PetscFunctionBegin;
89753cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
89853cdbc3dSStefano Zampini   PetscFunctionReturn(0);
89953cdbc3dSStefano Zampini }
9001e6b0712SBarry Smith 
90153cdbc3dSStefano Zampini /*@
902*f1580f4eSBarry Smith    PCBDDCGetNeumannBoundaries - Get parallel `IS` for Neumann boundaries
90353cdbc3dSStefano Zampini 
904*f1580f4eSBarry Smith    Not Collective
905785d1243SStefano Zampini 
906*f1580f4eSBarry Smith    Input Parameter:
907785d1243SStefano Zampini .  pc - the preconditioning context
908785d1243SStefano Zampini 
909*f1580f4eSBarry Smith    Output Parameter:
910785d1243SStefano Zampini .  NeumannBoundaries - index set defining the Neumann boundaries
911785d1243SStefano Zampini 
912785d1243SStefano Zampini    Level: intermediate
913785d1243SStefano Zampini 
914*f1580f4eSBarry Smith    Note:
915*f1580f4eSBarry Smith    The `IS` returned (if any) is the same passed in earlier by the user with `PCBDDCSetNeumannBoundaries()`
916785d1243SStefano Zampini 
917*f1580f4eSBarry Smith .seealso: `PCBDDC`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCGetDirichletBoundaries()`, `PCBDDCSetDirichletBoundaries()`
918785d1243SStefano Zampini @*/
9199371c9d4SSatish Balay PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc, IS *NeumannBoundaries) {
920785d1243SStefano Zampini   PetscFunctionBegin;
921785d1243SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
922cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetNeumannBoundaries_C", (PC, IS *), (pc, NeumannBoundaries));
923785d1243SStefano Zampini   PetscFunctionReturn(0);
924785d1243SStefano Zampini }
925785d1243SStefano Zampini 
9269371c9d4SSatish Balay static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc, IS *NeumannBoundaries) {
927785d1243SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
928785d1243SStefano Zampini 
929785d1243SStefano Zampini   PetscFunctionBegin;
930785d1243SStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundariesLocal;
931785d1243SStefano Zampini   PetscFunctionReturn(0);
932785d1243SStefano Zampini }
933785d1243SStefano Zampini 
93453cdbc3dSStefano Zampini /*@
935*f1580f4eSBarry Smith    PCBDDCGetNeumannBoundariesLocal - Get parallel `IS` for Neumann boundaries (in local ordering)
93653cdbc3dSStefano Zampini 
937*f1580f4eSBarry Smith    Not Collective
93853cdbc3dSStefano Zampini 
939*f1580f4eSBarry Smith    Input Parameter:
94028509bceSStefano Zampini .  pc - the preconditioning context
94153cdbc3dSStefano Zampini 
942*f1580f4eSBarry Smith    Output Parameter:
94328509bceSStefano Zampini .  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
94453cdbc3dSStefano Zampini 
94553cdbc3dSStefano Zampini    Level: intermediate
94653cdbc3dSStefano Zampini 
947*f1580f4eSBarry Smith    Note:
948*f1580f4eSBarry Smith    The `IS` returned could be the same passed in earlier by the user (if provided with `PCBDDCSetNeumannBoundariesLocal()`
949*f1580f4eSBarry Smith    or a global-to-local map of the global `IS` (if provided with `PCBDDCSetNeumannBoundaries()`).
950*f1580f4eSBarry Smith    In the latter case, the `IS` will be available after `PCSetUp()`.
95153cdbc3dSStefano Zampini 
952*f1580f4eSBarry Smith .seealso: `PCBDDC``PCBDDCSetNeumannBoundaries()`, `PCBDDCSetNeumannBoundariesLocal)`, `PCBDDCGetNeumannBoundaries()`
95353cdbc3dSStefano Zampini @*/
9549371c9d4SSatish Balay PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc, IS *NeumannBoundaries) {
95553cdbc3dSStefano Zampini   PetscFunctionBegin;
95653cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
957cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetNeumannBoundariesLocal_C", (PC, IS *), (pc, NeumannBoundaries));
9580c7d97c5SJed Brown   PetscFunctionReturn(0);
9590c7d97c5SJed Brown }
9601e6b0712SBarry Smith 
9619371c9d4SSatish Balay static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs, const PetscInt xadj[], const PetscInt adjncy[], PetscCopyMode copymode) {
96236e030ebSStefano Zampini   PC_BDDC    *pcbddc    = (PC_BDDC *)pc->data;
963da1bb401SStefano Zampini   PCBDDCGraph mat_graph = pcbddc->mat_graph;
96456282151SStefano Zampini   PetscBool   same_data = PETSC_FALSE;
96536e030ebSStefano Zampini 
96636e030ebSStefano Zampini   PetscFunctionBegin;
9678687889aSStefano Zampini   if (!nvtxs) {
96804194a47SStefano Zampini     if (copymode == PETSC_OWN_POINTER) {
9699566063dSJacob Faibussowitsch       PetscCall(PetscFree(xadj));
9709566063dSJacob Faibussowitsch       PetscCall(PetscFree(adjncy));
97104194a47SStefano Zampini     }
9729566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphResetCSR(mat_graph));
9738687889aSStefano Zampini     PetscFunctionReturn(0);
9748687889aSStefano Zampini   }
97566da6bd7Sstefano_zampini   if (mat_graph->nvtxs == nvtxs && mat_graph->freecsr) { /* we own the data */
97656282151SStefano Zampini     if (mat_graph->xadj == xadj && mat_graph->adjncy == adjncy) same_data = PETSC_TRUE;
97756282151SStefano Zampini     if (!same_data && mat_graph->xadj[nvtxs] == xadj[nvtxs]) {
9789566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(xadj, mat_graph->xadj, nvtxs + 1, &same_data));
97948a46eb9SPierre Jolivet       if (same_data) PetscCall(PetscArraycmp(adjncy, mat_graph->adjncy, xadj[nvtxs], &same_data));
98056282151SStefano Zampini     }
98156282151SStefano Zampini   }
98256282151SStefano Zampini   if (!same_data) {
983674ae819SStefano Zampini     /* free old CSR */
9849566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphResetCSR(mat_graph));
985674ae819SStefano Zampini     /* get CSR into graph structure */
986da1bb401SStefano Zampini     if (copymode == PETSC_COPY_VALUES) {
9879566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvtxs + 1, &mat_graph->xadj));
9889566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(xadj[nvtxs], &mat_graph->adjncy));
9899566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(mat_graph->xadj, xadj, nvtxs + 1));
9909566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(mat_graph->adjncy, adjncy, xadj[nvtxs]));
991a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
992da1bb401SStefano Zampini     } else if (copymode == PETSC_OWN_POINTER) {
9931a83f524SJed Brown       mat_graph->xadj    = (PetscInt *)xadj;
9941a83f524SJed Brown       mat_graph->adjncy  = (PetscInt *)adjncy;
995a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
996a1dbd327SStefano Zampini     } else if (copymode == PETSC_USE_POINTER) {
997a1dbd327SStefano Zampini       mat_graph->xadj    = (PetscInt *)xadj;
998a1dbd327SStefano Zampini       mat_graph->adjncy  = (PetscInt *)adjncy;
999a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_FALSE;
100063a3b9bcSJacob Faibussowitsch     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported copy mode %d", copymode);
1001575ad6abSStefano Zampini     mat_graph->nvtxs_csr         = nvtxs;
100256282151SStefano Zampini     pcbddc->recompute_topography = PETSC_TRUE;
100356282151SStefano Zampini   }
100436e030ebSStefano Zampini   PetscFunctionReturn(0);
100536e030ebSStefano Zampini }
10061e6b0712SBarry Smith 
100736e030ebSStefano Zampini /*@
100854fffbccSStefano Zampini    PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local degrees of freedom.
100936e030ebSStefano Zampini 
101036e030ebSStefano Zampini    Not collective
101136e030ebSStefano Zampini 
101236e030ebSStefano Zampini    Input Parameters:
101354fffbccSStefano Zampini +  pc - the preconditioning context.
101454fffbccSStefano Zampini .  nvtxs - number of local vertices of the graph (i.e., the number of local dofs).
101554fffbccSStefano Zampini .  xadj, adjncy - the connectivity of the dofs in CSR format.
1016*f1580f4eSBarry Smith -  copymode - supported modes are `PETSC_COPY_VALUES`, `PETSC_USE_POINTER` or `PETSC_OWN_POINTER`.
101736e030ebSStefano Zampini 
101836e030ebSStefano Zampini    Level: intermediate
101936e030ebSStefano Zampini 
1020*f1580f4eSBarry Smith    Note:
102195452b02SPatrick Sanan    A dof is considered connected with all local dofs if xadj[dof+1]-xadj[dof] == 1 and adjncy[xadj[dof]] is negative.
102236e030ebSStefano Zampini 
102316b07851SJed Brown .seealso: `PCBDDC`, `PetscCopyMode`
102436e030ebSStefano Zampini @*/
10259371c9d4SSatish Balay PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc, PetscInt nvtxs, const PetscInt xadj[], const PetscInt adjncy[], PetscCopyMode copymode) {
10260a545947SLisandro Dalcin   void (*f)(void) = NULL;
102736e030ebSStefano Zampini 
102836e030ebSStefano Zampini   PetscFunctionBegin;
102936e030ebSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
10308687889aSStefano Zampini   if (nvtxs) {
1031674ae819SStefano Zampini     PetscValidIntPointer(xadj, 3);
10321633d1f0SStefano Zampini     if (xadj[nvtxs]) PetscValidIntPointer(adjncy, 4);
10338687889aSStefano Zampini   }
1034cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetLocalAdjacencyGraph_C", (PC, PetscInt, const PetscInt[], const PetscInt[], PetscCopyMode), (pc, nvtxs, xadj, adjncy, copymode));
1035575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
10369566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", &f));
1037575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
10389566063dSJacob Faibussowitsch     PetscCall(PetscFree(xadj));
10399566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjncy));
1040da1bb401SStefano Zampini   }
104136e030ebSStefano Zampini   PetscFunctionReturn(0);
104236e030ebSStefano Zampini }
10431e6b0712SBarry Smith 
10449371c9d4SSatish Balay static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc, PetscInt n_is, IS ISForDofs[]) {
104563602bcaSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC *)pc->data;
104663602bcaSStefano Zampini   PetscInt  i;
104756282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
104863602bcaSStefano Zampini 
104963602bcaSStefano Zampini   PetscFunctionBegin;
105056282151SStefano Zampini   if (pcbddc->n_ISForDofsLocal == n_is) {
105156282151SStefano Zampini     for (i = 0; i < n_is; i++) {
105256282151SStefano Zampini       PetscBool isequalt;
10539566063dSJacob Faibussowitsch       PetscCall(ISEqual(ISForDofs[i], pcbddc->ISForDofsLocal[i], &isequalt));
105456282151SStefano Zampini       if (!isequalt) break;
105556282151SStefano Zampini     }
105656282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
105756282151SStefano Zampini   }
105848a46eb9SPierre Jolivet   for (i = 0; i < n_is; i++) PetscCall(PetscObjectReference((PetscObject)ISForDofs[i]));
105963602bcaSStefano Zampini   /* Destroy ISes if they were already set */
106048a46eb9SPierre Jolivet   for (i = 0; i < pcbddc->n_ISForDofsLocal; i++) PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i]));
10619566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofsLocal));
1062a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
106348a46eb9SPierre Jolivet   for (i = 0; i < pcbddc->n_ISForDofs; i++) PetscCall(ISDestroy(&pcbddc->ISForDofs[i]));
10649566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofs));
106563602bcaSStefano Zampini   pcbddc->n_ISForDofs = 0;
106663602bcaSStefano Zampini   /* allocate space then set */
106748a46eb9SPierre Jolivet   if (n_is) PetscCall(PetscMalloc1(n_is, &pcbddc->ISForDofsLocal));
1068ad540459SPierre Jolivet   for (i = 0; i < n_is; i++) pcbddc->ISForDofsLocal[i] = ISForDofs[i];
106963602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = n_is;
107063602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
107156282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
107263602bcaSStefano Zampini   PetscFunctionReturn(0);
107363602bcaSStefano Zampini }
107463602bcaSStefano Zampini 
107563602bcaSStefano Zampini /*@
107663602bcaSStefano Zampini    PCBDDCSetDofsSplittingLocal - Set index sets defining fields of the local subdomain matrix
107763602bcaSStefano Zampini 
107863602bcaSStefano Zampini    Collective
107963602bcaSStefano Zampini 
108063602bcaSStefano Zampini    Input Parameters:
108163602bcaSStefano Zampini +  pc - the preconditioning context
1082*f1580f4eSBarry Smith .  n_is - number of index sets defining the fields, must be the same on all MPI ranks
1083*f1580f4eSBarry Smith -  ISForDofs - array of `IS` describing the fields in local ordering
108463602bcaSStefano Zampini 
108563602bcaSStefano Zampini    Level: intermediate
108663602bcaSStefano Zampini 
1087*f1580f4eSBarry Smith    Note:
1088*f1580f4eSBarry Smith    Not all nodes need to be listed: unlisted nodes will belong to the complement field.
108963602bcaSStefano Zampini 
1090*f1580f4eSBarry Smith .seealso: `PCBDDC`, `PCBDDCSetDofsSplitting()`
109163602bcaSStefano Zampini @*/
10929371c9d4SSatish Balay PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc, PetscInt n_is, IS ISForDofs[]) {
109363602bcaSStefano Zampini   PetscInt i;
109463602bcaSStefano Zampini 
109563602bcaSStefano Zampini   PetscFunctionBegin;
109663602bcaSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
109763602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc, n_is, 2);
109863602bcaSStefano Zampini   for (i = 0; i < n_is; i++) {
109963602bcaSStefano Zampini     PetscCheckSameComm(pc, 1, ISForDofs[i], 3);
110063602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i], IS_CLASSID, 3);
110163602bcaSStefano Zampini   }
1102cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDofsSplittingLocal_C", (PC, PetscInt, IS[]), (pc, n_is, ISForDofs));
110363602bcaSStefano Zampini   PetscFunctionReturn(0);
110463602bcaSStefano Zampini }
110563602bcaSStefano Zampini 
11069371c9d4SSatish Balay static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc, PetscInt n_is, IS ISForDofs[]) {
11079c0446d6SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC *)pc->data;
11089c0446d6SStefano Zampini   PetscInt  i;
110956282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
11109c0446d6SStefano Zampini 
11119c0446d6SStefano Zampini   PetscFunctionBegin;
111256282151SStefano Zampini   if (pcbddc->n_ISForDofs == n_is) {
111356282151SStefano Zampini     for (i = 0; i < n_is; i++) {
111456282151SStefano Zampini       PetscBool isequalt;
11159566063dSJacob Faibussowitsch       PetscCall(ISEqual(ISForDofs[i], pcbddc->ISForDofs[i], &isequalt));
111656282151SStefano Zampini       if (!isequalt) break;
111756282151SStefano Zampini     }
111856282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
111956282151SStefano Zampini   }
112048a46eb9SPierre Jolivet   for (i = 0; i < n_is; i++) PetscCall(PetscObjectReference((PetscObject)ISForDofs[i]));
1121da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
112248a46eb9SPierre Jolivet   for (i = 0; i < pcbddc->n_ISForDofs; i++) PetscCall(ISDestroy(&pcbddc->ISForDofs[i]));
11239566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofs));
1124a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
112548a46eb9SPierre Jolivet   for (i = 0; i < pcbddc->n_ISForDofsLocal; i++) PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i]));
11269566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofsLocal));
112763602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = 0;
1128da1bb401SStefano Zampini   /* allocate space then set */
112948a46eb9SPierre Jolivet   if (n_is) PetscCall(PetscMalloc1(n_is, &pcbddc->ISForDofs));
1130ad540459SPierre Jolivet   for (i = 0; i < n_is; i++) pcbddc->ISForDofs[i] = ISForDofs[i];
11319c0446d6SStefano Zampini   pcbddc->n_ISForDofs = n_is;
113263602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
113356282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
11349c0446d6SStefano Zampini   PetscFunctionReturn(0);
11359c0446d6SStefano Zampini }
11361e6b0712SBarry Smith 
11379c0446d6SStefano Zampini /*@
113863602bcaSStefano Zampini    PCBDDCSetDofsSplitting - Set index sets defining fields of the global matrix
11399c0446d6SStefano Zampini 
114063602bcaSStefano Zampini    Collective
11419c0446d6SStefano Zampini 
11429c0446d6SStefano Zampini    Input Parameters:
11439c0446d6SStefano Zampini +  pc - the preconditioning context
11440f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
11450f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in global ordering
11469c0446d6SStefano Zampini 
11479c0446d6SStefano Zampini    Level: intermediate
11489c0446d6SStefano Zampini 
1149*f1580f4eSBarry Smith    Note:
11500f202f7eSStefano Zampini    Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
11519c0446d6SStefano Zampini 
1152*f1580f4eSBarry Smith .seealso: `PCBDDC`, `PCBDDCSetDofsSplittingLocal()`
11539c0446d6SStefano Zampini @*/
11549371c9d4SSatish Balay PetscErrorCode PCBDDCSetDofsSplitting(PC pc, PetscInt n_is, IS ISForDofs[]) {
11552b510759SStefano Zampini   PetscInt i;
11569c0446d6SStefano Zampini 
11579c0446d6SStefano Zampini   PetscFunctionBegin;
11589c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
115963602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc, n_is, 2);
11602b510759SStefano Zampini   for (i = 0; i < n_is; i++) {
116163602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i], IS_CLASSID, 3);
1162a011d5a7Sstefano_zampini     PetscCheckSameComm(pc, 1, ISForDofs[i], 3);
11632b510759SStefano Zampini   }
1164cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDofsSplitting_C", (PC, PetscInt, IS[]), (pc, n_is, ISForDofs));
11659c0446d6SStefano Zampini   PetscFunctionReturn(0);
11669c0446d6SStefano Zampini }
1167906d46d4SStefano Zampini 
1168534831adSStefano Zampini /*
1169534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
1170534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
11719c0446d6SStefano Zampini 
1172534831adSStefano Zampini    Input Parameter:
1173966d8056SPierre Jolivet +  pc - the preconditioner context
1174534831adSStefano Zampini 
1175*f1580f4eSBarry Smith    Note:
1176534831adSStefano Zampini      The interface routine PCPreSolve() is not usually called directly by
1177534831adSStefano Zampini    the user, but instead is called by KSPSolve().
1178534831adSStefano Zampini */
11799371c9d4SSatish Balay static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x) {
1180534831adSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC *)pc->data;
1181534831adSStefano Zampini   PC_IS    *pcis   = (PC_IS *)(pc->data);
11823972b0daSStefano Zampini   Vec       used_vec;
1183fcb54b1cSPierre Jolivet   PetscBool iscg, save_rhs = PETSC_TRUE, benign_correction_computed;
1184534831adSStefano Zampini 
1185534831adSStefano Zampini   PetscFunctionBegin;
11861f4df5f7SStefano Zampini   /* if we are working with CG, one dirichlet solve can be avoided during Krylov iterations */
118785c4d303SStefano Zampini   if (ksp) {
1188fcb54b1cSPierre Jolivet     PetscCall(PetscObjectTypeCompareAny((PetscObject)ksp, &iscg, KSPCG, KSPGROPPCG, KSPPIPECG, KSPPIPELCG, KSPPIPECGRR, ""));
118948a46eb9SPierre Jolivet     if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || !iscg || pc->mat != pc->pmat) PetscCall(PCBDDCSetUseExactDirichlet(pc, PETSC_FALSE));
119085c4d303SStefano Zampini   }
119148a46eb9SPierre Jolivet   if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || pc->mat != pc->pmat) PetscCall(PCBDDCSetUseExactDirichlet(pc, PETSC_FALSE));
11921f4df5f7SStefano Zampini 
119385c4d303SStefano Zampini   /* Creates parallel work vectors used in presolve */
119448a46eb9SPierre Jolivet   if (!pcbddc->original_rhs) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->original_rhs));
119548a46eb9SPierre Jolivet   if (!pcbddc->temp_solution) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->temp_solution));
11968d00608fSStefano Zampini 
119727b6a85dSStefano Zampini   pcbddc->temp_solution_used = PETSC_FALSE;
11983972b0daSStefano Zampini   if (x) {
11999566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)x));
12003972b0daSStefano Zampini     used_vec = x;
12018d00608fSStefano Zampini   } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */
12029566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pcbddc->temp_solution));
12033972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
12049566063dSJacob Faibussowitsch     PetscCall(VecSet(used_vec, 0.0));
120527b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
12069566063dSJacob Faibussowitsch     PetscCall(VecCopy(rhs, pcbddc->original_rhs));
1207266e20e9SStefano Zampini     save_rhs                  = PETSC_FALSE;
1208266e20e9SStefano Zampini     pcbddc->eliminate_dirdofs = PETSC_TRUE;
12093972b0daSStefano Zampini   }
12108efcfb23SStefano Zampini 
12118efcfb23SStefano Zampini   /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */
12123972b0daSStefano Zampini   if (ksp) {
1213a0cb1b98SStefano Zampini     /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */
12149566063dSJacob Faibussowitsch     PetscCall(KSPGetInitialGuessNonzero(ksp, &pcbddc->ksp_guess_nonzero));
121548a46eb9SPierre Jolivet     if (!pcbddc->ksp_guess_nonzero) PetscCall(VecSet(used_vec, 0.0));
12163972b0daSStefano Zampini   }
12173308cffdSStefano Zampini 
12188d00608fSStefano Zampini   pcbddc->rhs_change = PETSC_FALSE;
12193972b0daSStefano Zampini   /* Take into account zeroed rows -> change rhs and store solution removed */
122070c64980SStefano Zampini   if (rhs && pcbddc->eliminate_dirdofs) {
12213975b054SStefano Zampini     IS dirIS = NULL;
12223975b054SStefano Zampini 
1223a07ea27aSStefano Zampini     /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */
12249566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph, &dirIS));
12253975b054SStefano Zampini     if (dirIS) {
1226906d46d4SStefano Zampini       Mat_IS            *matis = (Mat_IS *)pc->pmat->data;
1227785d1243SStefano Zampini       PetscInt           dirsize, i, *is_indices;
12282b095fd8SStefano Zampini       PetscScalar       *array_x;
12292b095fd8SStefano Zampini       const PetscScalar *array_diagonal;
1230785d1243SStefano Zampini 
12319566063dSJacob Faibussowitsch       PetscCall(MatGetDiagonal(pc->pmat, pcis->vec1_global));
12329566063dSJacob Faibussowitsch       PetscCall(VecPointwiseDivide(pcis->vec1_global, rhs, pcis->vec1_global));
12339566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_global, pcis->vec2_N, INSERT_VALUES, SCATTER_FORWARD));
12349566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_global, pcis->vec2_N, INSERT_VALUES, SCATTER_FORWARD));
12359566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx, used_vec, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD));
12369566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx, used_vec, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD));
12379566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(dirIS, &dirsize));
12389566063dSJacob Faibussowitsch       PetscCall(VecGetArray(pcis->vec1_N, &array_x));
12399566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(pcis->vec2_N, &array_diagonal));
12409566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(dirIS, (const PetscInt **)&is_indices));
12412fa5cd67SKarl Rupp       for (i = 0; i < dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
12429566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(dirIS, (const PetscInt **)&is_indices));
12439566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(pcis->vec2_N, &array_diagonal));
12449566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(pcis->vec1_N, &array_x));
12459566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_N, used_vec, INSERT_VALUES, SCATTER_REVERSE));
12469566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_N, used_vec, INSERT_VALUES, SCATTER_REVERSE));
12478d00608fSStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
12489566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&dirIS));
12498efcfb23SStefano Zampini     }
1250a07ea27aSStefano Zampini   }
1251b76ba322SStefano Zampini 
12528efcfb23SStefano Zampini   /* remove the computed solution or the initial guess from the rhs */
12538d00608fSStefano Zampini   if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero)) {
125427b6a85dSStefano Zampini     /* save the original rhs */
125527b6a85dSStefano Zampini     if (save_rhs) {
12569566063dSJacob Faibussowitsch       PetscCall(VecSwap(rhs, pcbddc->original_rhs));
125727b6a85dSStefano Zampini       save_rhs = PETSC_FALSE;
12588d00608fSStefano Zampini     }
12598d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
12609566063dSJacob Faibussowitsch     PetscCall(VecScale(used_vec, -1.0));
12619566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(pc->mat, used_vec, pcbddc->original_rhs, rhs));
12629566063dSJacob Faibussowitsch     PetscCall(VecScale(used_vec, -1.0));
12639566063dSJacob Faibussowitsch     PetscCall(VecCopy(used_vec, pcbddc->temp_solution));
126427b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
12651baa6e33SBarry Smith     if (ksp) PetscCall(KSPSetInitialGuessNonzero(ksp, PETSC_FALSE));
12663308cffdSStefano Zampini   }
12679566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&used_vec));
1268b76ba322SStefano Zampini 
1269fc17d649SStefano Zampini   /* compute initial vector in benign space if needed
127027b6a85dSStefano Zampini      and remove non-benign solution from the rhs */
127127b6a85dSStefano Zampini   benign_correction_computed = PETSC_FALSE;
127208af2428SStefano Zampini   if (rhs && pcbddc->benign_compute_correction && (pcbddc->benign_have_null || pcbddc->benign_apply_coarse_only)) {
12731f4df5f7SStefano Zampini     /* compute u^*_h using ideas similar to those in Xuemin Tu's PhD thesis (see Section 4.8.1)
12741f4df5f7SStefano Zampini        Recursively apply BDDC in the multilevel case */
127548a46eb9SPierre Jolivet     if (!pcbddc->benign_vec) PetscCall(VecDuplicate(rhs, &pcbddc->benign_vec));
1276c69e9cc1SStefano Zampini     /* keep applying coarse solver unless we no longer have benign subdomains */
1277c69e9cc1SStefano Zampini     pcbddc->benign_apply_coarse_only = pcbddc->benign_have_null ? PETSC_TRUE : PETSC_FALSE;
127827b6a85dSStefano Zampini     if (!pcbddc->benign_skip_correction) {
12799566063dSJacob Faibussowitsch       PetscCall(PCApply_BDDC(pc, rhs, pcbddc->benign_vec));
12803bca92a6SStefano Zampini       benign_correction_computed = PETSC_TRUE;
12811baa6e33SBarry Smith       if (pcbddc->temp_solution_used) PetscCall(VecAXPY(pcbddc->temp_solution, 1.0, pcbddc->benign_vec));
12829566063dSJacob Faibussowitsch       PetscCall(VecScale(pcbddc->benign_vec, -1.0));
128327b6a85dSStefano Zampini       /* store the original rhs if not done earlier */
12841baa6e33SBarry Smith       if (save_rhs) PetscCall(VecSwap(rhs, pcbddc->original_rhs));
128527b6a85dSStefano Zampini       if (pcbddc->rhs_change) {
12869566063dSJacob Faibussowitsch         PetscCall(MatMultAdd(pc->mat, pcbddc->benign_vec, rhs, rhs));
128727b6a85dSStefano Zampini       } else {
12889566063dSJacob Faibussowitsch         PetscCall(MatMultAdd(pc->mat, pcbddc->benign_vec, pcbddc->original_rhs, rhs));
128927b6a85dSStefano Zampini       }
12900369aaf7SStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
129127b6a85dSStefano Zampini     }
129227b6a85dSStefano Zampini     pcbddc->benign_apply_coarse_only = PETSC_FALSE;
12934df7a6bfSStefano Zampini   } else {
12949566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&pcbddc->benign_vec));
12950369aaf7SStefano Zampini   }
12962d4c4fecSStefano Zampini 
12972d4c4fecSStefano Zampini   /* dbg output */
1298a198735bSStefano Zampini   if (pcbddc->dbg_flag && benign_correction_computed) {
12991f4df5f7SStefano Zampini     Vec v;
1300c69e9cc1SStefano Zampini 
13019566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_global, &v));
1302c69e9cc1SStefano Zampini     if (pcbddc->ChangeOfBasisMatrix) {
13039566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, rhs, v));
1304c69e9cc1SStefano Zampini     } else {
13059566063dSJacob Faibussowitsch       PetscCall(VecCopy(rhs, v));
1306c69e9cc1SStefano Zampini     }
13079566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, v, PETSC_TRUE));
130863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "LEVEL %" PetscInt_FMT ": is the correction benign?\n", pcbddc->current_level));
13099566063dSJacob Faibussowitsch     PetscCall(PetscScalarView(pcbddc->benign_n, pcbddc->benign_p0, pcbddc->dbg_viewer));
13109566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
13119566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&v));
13121f4df5f7SStefano Zampini   }
13130369aaf7SStefano Zampini 
13140369aaf7SStefano Zampini   /* set initial guess if using PCG */
13158ae0ca82SStefano Zampini   pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
13160369aaf7SStefano Zampini   if (x && pcbddc->use_exact_dirichlet_trick) {
13179566063dSJacob Faibussowitsch     PetscCall(VecSet(x, 0.0));
13181dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
131927b6a85dSStefano Zampini       if (benign_correction_computed) { /* we have already saved the changed rhs */
13209566063dSJacob Faibussowitsch         PetscCall(VecLockReadPop(pcis->vec1_global));
13211dd7afcfSStefano Zampini       } else {
13229566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, rhs, pcis->vec1_global));
13231dd7afcfSStefano Zampini       }
13249566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_global, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
13259566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_global, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
13261dd7afcfSStefano Zampini     } else {
13279566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D, rhs, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
13289566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D, rhs, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
13291dd7afcfSStefano Zampini     }
13309566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
13319566063dSJacob Faibussowitsch     PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D));
13329566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
13339566063dSJacob Faibussowitsch     PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D));
13341dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
13359566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_global, 0.));
13369566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, pcis->vec1_global, INSERT_VALUES, SCATTER_REVERSE));
13379566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, pcis->vec1_global, INSERT_VALUES, SCATTER_REVERSE));
13389566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcis->vec1_global, x));
13391dd7afcfSStefano Zampini     } else {
13409566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, x, INSERT_VALUES, SCATTER_REVERSE));
13419566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, x, INSERT_VALUES, SCATTER_REVERSE));
13421dd7afcfSStefano Zampini     }
13431baa6e33SBarry Smith     if (ksp) PetscCall(KSPSetInitialGuessNonzero(ksp, PETSC_TRUE));
13448ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_TRUE;
1345266e20e9SStefano Zampini   } else if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior && benign_correction_computed && pcbddc->use_exact_dirichlet_trick) {
13469566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(pcis->vec1_global));
13470369aaf7SStefano Zampini   }
1348534831adSStefano Zampini   PetscFunctionReturn(0);
1349534831adSStefano Zampini }
1350906d46d4SStefano Zampini 
1351534831adSStefano Zampini /*
1352534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
1353534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
1354534831adSStefano Zampini 
1355534831adSStefano Zampini    Input Parameter:
1356966d8056SPierre Jolivet +  pc - the preconditioner context
1357534831adSStefano Zampini 
1358534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
1359534831adSStefano Zampini 
1360*f1580f4eSBarry Smith    Note:
1361534831adSStefano Zampini      The interface routine PCPostSolve() is not usually called directly by
1362534831adSStefano Zampini      the user, but instead is called by KSPSolve().
1363534831adSStefano Zampini */
13649371c9d4SSatish Balay static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x) {
1365534831adSStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
1366534831adSStefano Zampini 
1367534831adSStefano Zampini   PetscFunctionBegin;
13683972b0daSStefano Zampini   /* add solution removed in presolve */
13696bcfc461SStefano Zampini   if (x && pcbddc->rhs_change) {
137027b6a85dSStefano Zampini     if (pcbddc->temp_solution_used) {
13719566063dSJacob Faibussowitsch       PetscCall(VecAXPY(x, 1.0, pcbddc->temp_solution));
1372af140850Sstefano_zampini     } else if (pcbddc->benign_compute_correction && pcbddc->benign_vec) {
13739566063dSJacob Faibussowitsch       PetscCall(VecAXPY(x, -1.0, pcbddc->benign_vec));
13743425bc38SStefano Zampini     }
1375af140850Sstefano_zampini     /* restore to original state (not for FETI-DP) */
1376af140850Sstefano_zampini     if (ksp) pcbddc->temp_solution_used = PETSC_FALSE;
137727b6a85dSStefano Zampini   }
137827b6a85dSStefano Zampini 
1379266e20e9SStefano Zampini   /* restore rhs to its original state (not needed for FETI-DP) */
13808d00608fSStefano Zampini   if (rhs && pcbddc->rhs_change) {
13819566063dSJacob Faibussowitsch     PetscCall(VecSwap(rhs, pcbddc->original_rhs));
13828d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_FALSE;
1383af140850Sstefano_zampini   }
13848efcfb23SStefano Zampini   /* restore ksp guess state */
13858efcfb23SStefano Zampini   if (ksp) {
13869566063dSJacob Faibussowitsch     PetscCall(KSPSetInitialGuessNonzero(ksp, pcbddc->ksp_guess_nonzero));
13878ae0ca82SStefano Zampini     /* reset flag for exact dirichlet trick */
13888ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
1389af140850Sstefano_zampini   }
1390534831adSStefano Zampini   PetscFunctionReturn(0);
1391534831adSStefano Zampini }
1392af140850Sstefano_zampini 
13930c7d97c5SJed Brown /*
13940c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
13950c7d97c5SJed Brown                   by setting data structures and options.
13960c7d97c5SJed Brown 
13970c7d97c5SJed Brown    Input Parameter:
139853cdbc3dSStefano Zampini +  pc - the preconditioner context
13990c7d97c5SJed Brown 
14000c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
14010c7d97c5SJed Brown 
1402*f1580f4eSBarry Smith    Note:
14030c7d97c5SJed Brown      The interface routine PCSetUp() is not usually called directly by
14040c7d97c5SJed Brown      the user, but instead is called by PCApply() if necessary.
14050c7d97c5SJed Brown */
14069371c9d4SSatish Balay PetscErrorCode PCSetUp_BDDC(PC pc) {
14070c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC *)pc->data;
1408c703fcc7SStefano Zampini   PCBDDCSubSchurs sub_schurs;
14095e8657edSStefano Zampini   Mat_IS         *matis;
141008122e43SStefano Zampini   MatNullSpace    nearnullspace;
141135509ce9Sstefano_zampini   Mat             lA;
141235509ce9Sstefano_zampini   IS              lP, zerodiag = NULL;
141391e8d312SStefano Zampini   PetscInt        nrows, ncols;
141486bfa4cfSStefano Zampini   PetscMPIInt     size;
1415c703fcc7SStefano Zampini   PetscBool       computesubschurs;
14168de1fae6SStefano Zampini   PetscBool       computeconstraintsmatrix;
14173b03f7bbSStefano Zampini   PetscBool       new_nearnullspace_provided, ismatis, rl;
1418b94d7dedSBarry Smith   PetscBool       isset, issym, isspd;
14190c7d97c5SJed Brown 
14200c7d97c5SJed Brown   PetscFunctionBegin;
14219566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATIS, &ismatis));
142228b400f6SJacob Faibussowitsch   PetscCheck(ismatis, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "PCBDDC preconditioner requires matrix of type MATIS");
14239566063dSJacob Faibussowitsch   PetscCall(MatGetSize(pc->pmat, &nrows, &ncols));
14247827d75bSBarry Smith   PetscCheck(nrows == ncols, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "PCBDDC preconditioner requires a square preconditioning matrix");
14259566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
142686bfa4cfSStefano Zampini 
14275e8657edSStefano Zampini   matis = (Mat_IS *)pc->pmat->data;
1428f4ddd8eeSStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */
14293b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
143071582508SStefano Zampini      Also, BDDC builds its own KSP for the Dirichlet problem */
14313b03f7bbSStefano Zampini   rl    = pcbddc->recompute_topography;
14323b03f7bbSStefano Zampini   if (!pc->setupcalled || pc->flag == DIFFERENT_NONZERO_PATTERN) rl = PETSC_TRUE;
14331c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&rl, &pcbddc->recompute_topography, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc)));
1434c83e1ba7SStefano Zampini   if (pcbddc->recompute_topography) {
1435c83e1ba7SStefano Zampini     pcbddc->graphanalyzed    = PETSC_FALSE;
1436c83e1ba7SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1437c83e1ba7SStefano Zampini   } else {
14388de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_FALSE;
1439c83e1ba7SStefano Zampini   }
1440b087196eSStefano Zampini 
1441b087196eSStefano Zampini   /* check parameters' compatibility */
1442b7ab4a40SStefano Zampini   if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE;
1443bd2a564bSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_threshold[0] != 0.0 || pcbddc->adaptive_threshold[1] != 0.0);
144486bfa4cfSStefano Zampini   pcbddc->use_deluxe_scaling   = (PetscBool)(pcbddc->use_deluxe_scaling && size > 1);
144586bfa4cfSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_selection && size > 1);
1446bf3a8328SStefano Zampini   pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined);
1447862806e4SStefano Zampini   if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE;
1448862806e4SStefano Zampini 
14495a95e1ceSStefano Zampini   computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling);
145016909a7fSStefano Zampini 
145171582508SStefano Zampini   /* activate all connected components if the netflux has been requested */
1452bb05f991SStefano Zampini   if (pcbddc->compute_nonetflux) {
1453bb05f991SStefano Zampini     pcbddc->use_vertices = PETSC_TRUE;
1454bb05f991SStefano Zampini     pcbddc->use_edges    = PETSC_TRUE;
1455bb05f991SStefano Zampini     pcbddc->use_faces    = PETSC_TRUE;
1456bb05f991SStefano Zampini   }
1457bb05f991SStefano Zampini 
1458f4ddd8eeSStefano Zampini   /* Get stdout for dbg */
145970cf5478SStefano Zampini   if (pcbddc->dbg_flag) {
1460ad540459SPierre Jolivet     if (!pcbddc->dbg_viewer) pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc));
14619566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer));
14629566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIAddTab(pcbddc->dbg_viewer, 2 * pcbddc->current_level));
1463f4ddd8eeSStefano Zampini   }
1464f4ddd8eeSStefano Zampini 
1465c703fcc7SStefano Zampini   /* process topology information */
14669566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Topology[pcbddc->current_level], pc, 0, 0, 0));
146771582508SStefano Zampini   if (pcbddc->recompute_topography) {
14689566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeLocalTopologyInfo(pc));
14691baa6e33SBarry Smith     if (pcbddc->discretegradient) PetscCall(PCBDDCNedelecSupport(pc));
1470c703fcc7SStefano Zampini   }
14714f819b78SStefano Zampini   if (pcbddc->corner_selected) pcbddc->use_vertices = PETSC_TRUE;
1472a13144ffSStefano Zampini 
1473c703fcc7SStefano Zampini   /* change basis if requested by the user */
14745e8657edSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) {
14755e8657edSStefano Zampini     /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */
14765e8657edSStefano Zampini     pcbddc->use_change_of_basis = PETSC_FALSE;
14779566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeLocalMatrix(pc, pcbddc->user_ChangeOfBasisMatrix));
14785e8657edSStefano Zampini   } else {
14799566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcbddc->local_mat));
14809566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)matis->A));
14815e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
1482d16cbb6bSStefano Zampini   }
1483d16cbb6bSStefano Zampini 
14844f1b2e48SStefano Zampini   /*
1485c703fcc7SStefano Zampini      Compute change of basis on local pressures (aka zerodiag dofs) with the benign trick
14864f1b2e48SStefano Zampini      This should come earlier then PCISSetUp for extracting the correct subdomain matrices
14874f1b2e48SStefano Zampini   */
14889566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignShellMat(pc, PETSC_TRUE));
1489d16cbb6bSStefano Zampini   if (pcbddc->benign_saddle_point) {
14909f47a83aSStefano Zampini     PC_IS *pcis = (PC_IS *)pc->data;
14919f47a83aSStefano Zampini 
149205b28244SStefano Zampini     if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE;
14933b03f7bbSStefano Zampini     /* detect local saddle point and change the basis in pcbddc->local_mat */
14949566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignDetectSaddlePoint(pc, (PetscBool)(!pcbddc->recompute_topography), &zerodiag));
1495a3df083aSStefano Zampini     /* pop B0 mat from local mat */
14969566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignPopOrPushB0(pc, PETSC_TRUE));
14971dd7afcfSStefano Zampini     /* give pcis a hint to not reuse submatrices during PCISCreate */
14981dd7afcfSStefano Zampini     if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) {
14991dd7afcfSStefano Zampini       if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) {
15001dd7afcfSStefano Zampini         pcis->reusesubmatrices = PETSC_FALSE;
15011dd7afcfSStefano Zampini       } else {
1502a3df083aSStefano Zampini         pcis->reusesubmatrices = PETSC_TRUE;
15031dd7afcfSStefano Zampini       }
1504a3df083aSStefano Zampini     } else {
15059f47a83aSStefano Zampini       pcis->reusesubmatrices = PETSC_FALSE;
1506674ae819SStefano Zampini     }
1507a3df083aSStefano Zampini   }
150827b6a85dSStefano Zampini 
15098037d520SStefano Zampini   /* propagate relevant information */
1510b94d7dedSBarry Smith   PetscCall(MatIsSymmetricKnown(matis->A, &isset, &issym));
1511b94d7dedSBarry Smith   if (isset) PetscCall(MatSetOption(pcbddc->local_mat, MAT_SYMMETRIC, issym));
1512b94d7dedSBarry Smith   PetscCall(MatIsSPDKnown(matis->A, &isset, &isspd));
1513b94d7dedSBarry Smith   if (isset) PetscCall(MatSetOption(pcbddc->local_mat, MAT_SPD, isspd));
1514e496cd5dSStefano Zampini 
15155e8657edSStefano Zampini   /* Set up all the "iterative substructuring" common block without computing solvers */
15165e8657edSStefano Zampini   {
15175e8657edSStefano Zampini     Mat temp_mat;
15185e8657edSStefano Zampini 
15195e8657edSStefano Zampini     temp_mat = matis->A;
15205e8657edSStefano Zampini     matis->A = pcbddc->local_mat;
15219566063dSJacob Faibussowitsch     PetscCall(PCISSetUp(pc, PETSC_TRUE, PETSC_FALSE));
15225e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
15235e8657edSStefano Zampini     matis->A          = temp_mat;
15245e8657edSStefano Zampini   }
1525684f6988SStefano Zampini 
152681d14e9dSStefano Zampini   /* Analyze interface */
152764ac59b8SStefano Zampini   if (!pcbddc->graphanalyzed) {
15289566063dSJacob Faibussowitsch     PetscCall(PCBDDCAnalyzeInterface(pc));
15298de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1530345ecf6cSStefano Zampini     if (pcbddc->adaptive_selection && !pcbddc->use_deluxe_scaling && !pcbddc->mat_graph->twodim) {
15314247aa23Sstefano_zampini       SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot compute the adaptive primal space for a problem with 3D edges without deluxe scaling");
1532345ecf6cSStefano Zampini     }
1533a198735bSStefano Zampini     if (pcbddc->compute_nonetflux) {
1534669cc0f4SStefano Zampini       MatNullSpace nnfnnsp;
1535669cc0f4SStefano Zampini 
153628b400f6SJacob Faibussowitsch       PetscCheck(pcbddc->divudotp, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Missing divudotp operator");
15379566063dSJacob Faibussowitsch       PetscCall(PCBDDCComputeNoNetFlux(pc->pmat, pcbddc->divudotp, pcbddc->divudotp_trans, pcbddc->divudotp_vl2l, pcbddc->mat_graph, &nnfnnsp));
153871582508SStefano Zampini       /* TODO what if a nearnullspace is already attached? */
15398037d520SStefano Zampini       if (nnfnnsp) {
15409566063dSJacob Faibussowitsch         PetscCall(MatSetNearNullSpace(pc->pmat, nnfnnsp));
15419566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceDestroy(&nnfnnsp));
1542669cc0f4SStefano Zampini       }
1543674ae819SStefano Zampini     }
15448037d520SStefano Zampini   }
15459566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Topology[pcbddc->current_level], pc, 0, 0, 0));
1546fb8d54d4SStefano Zampini 
15475408967cSStefano Zampini   /* check existence of a divergence free extension, i.e.
15485408967cSStefano Zampini      b(v_I,p_0) = 0 for all v_I (raise error if not).
15495408967cSStefano Zampini      Also, check that PCBDDCBenignGetOrSetP0 works */
155048a46eb9SPierre Jolivet   if (pcbddc->benign_saddle_point && pcbddc->dbg_flag > 1) PetscCall(PCBDDCBenignCheck(pc, zerodiag));
15519566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&zerodiag));
155206f24817SStefano Zampini 
1553b96c3477SStefano Zampini   /* Setup local dirichlet solver ksp_D and sub_schurs solvers */
155448a46eb9SPierre Jolivet   if (computesubschurs && pcbddc->recompute_topography) PetscCall(PCBDDCInitSubSchurs(pc));
15559d54b7f4SStefano Zampini   /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/
155648a46eb9SPierre Jolivet   if (!pcbddc->use_deluxe_scaling) PetscCall(PCBDDCScalingSetUp(pc));
1557c703fcc7SStefano Zampini 
1558c703fcc7SStefano Zampini   /* finish setup solvers and do adaptive selection of constraints */
1559b334f244SStefano Zampini   sub_schurs = pcbddc->sub_schurs;
1560b334f244SStefano Zampini   if (sub_schurs && sub_schurs->schur_explicit) {
15611baa6e33SBarry Smith     if (computesubschurs) PetscCall(PCBDDCSetUpSubSchurs(pc));
15629566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetUpLocalSolvers(pc, PETSC_TRUE, PETSC_FALSE));
1563d5574798SStefano Zampini   } else {
15649566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetUpLocalSolvers(pc, PETSC_TRUE, PETSC_FALSE));
15651baa6e33SBarry Smith     if (computesubschurs) PetscCall(PCBDDCSetUpSubSchurs(pc));
15662070dbb6SStefano Zampini   }
156708122e43SStefano Zampini   if (pcbddc->adaptive_selection) {
15689566063dSJacob Faibussowitsch     PetscCall(PCBDDCAdaptiveSelection(pc));
15698de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1570b7eb3628SStefano Zampini   }
1571684f6988SStefano Zampini 
1572f4ddd8eeSStefano Zampini   /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */
1573fb8d54d4SStefano Zampini   new_nearnullspace_provided = PETSC_FALSE;
15749566063dSJacob Faibussowitsch   PetscCall(MatGetNearNullSpace(pc->pmat, &nearnullspace));
1575f4ddd8eeSStefano Zampini   if (pcbddc->onearnullspace) { /* already used nearnullspace */
1576f4ddd8eeSStefano Zampini     if (!nearnullspace) {       /* near null space attached to mat has been destroyed */
1577f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1578f4ddd8eeSStefano Zampini     } else {
1579f4ddd8eeSStefano Zampini       /* determine if the two nullspaces are different (should be lightweight) */
1580f4ddd8eeSStefano Zampini       if (nearnullspace != pcbddc->onearnullspace) {
1581f4ddd8eeSStefano Zampini         new_nearnullspace_provided = PETSC_TRUE;
1582165b64e2SStefano Zampini       } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */
1583f4ddd8eeSStefano Zampini         PetscInt         i;
1584165b64e2SStefano Zampini         const Vec       *nearnullvecs;
1585165b64e2SStefano Zampini         PetscObjectState state;
1586165b64e2SStefano Zampini         PetscInt         nnsp_size;
15879566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceGetVecs(nearnullspace, NULL, &nnsp_size, &nearnullvecs));
1588f4ddd8eeSStefano Zampini         for (i = 0; i < nnsp_size; i++) {
15899566063dSJacob Faibussowitsch           PetscCall(PetscObjectStateGet((PetscObject)nearnullvecs[i], &state));
1590165b64e2SStefano Zampini           if (pcbddc->onearnullvecs_state[i] != state) {
1591f4ddd8eeSStefano Zampini             new_nearnullspace_provided = PETSC_TRUE;
1592f4ddd8eeSStefano Zampini             break;
1593f4ddd8eeSStefano Zampini           }
1594f4ddd8eeSStefano Zampini         }
1595f4ddd8eeSStefano Zampini       }
1596f4ddd8eeSStefano Zampini     }
1597f4ddd8eeSStefano Zampini   } else {
1598f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* both nearnullspaces are null */
1599f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_FALSE;
1600f4ddd8eeSStefano Zampini     } else { /* nearnullspace attached later */
1601f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1602f4ddd8eeSStefano Zampini     }
1603f4ddd8eeSStefano Zampini   }
1604f4ddd8eeSStefano Zampini 
1605f4ddd8eeSStefano Zampini   /* Setup constraints and related work vectors */
1606727cdba6SStefano Zampini   /* reset primal space flags */
16079566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_LocalWork[pcbddc->current_level], pc, 0, 0, 0));
1608f4ddd8eeSStefano Zampini   pcbddc->new_primal_space       = PETSC_FALSE;
1609727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_FALSE;
16108de1fae6SStefano Zampini   if (computeconstraintsmatrix || new_nearnullspace_provided) {
1611727cdba6SStefano Zampini     /* It also sets the primal space flags */
16129566063dSJacob Faibussowitsch     PetscCall(PCBDDCConstraintsSetUp(pc));
16139543d0ffSStefano Zampini   }
1614e7b262bdSStefano Zampini   /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */
16159566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetUpLocalWorkVectors(pc));
16165e8657edSStefano Zampini 
16175e8657edSStefano Zampini   if (pcbddc->use_change_of_basis) {
16185e8657edSStefano Zampini     PC_IS *pcis = (PC_IS *)(pc->data);
16195e8657edSStefano Zampini 
16209566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeLocalMatrix(pc, pcbddc->ChangeOfBasisMatrix));
16214f1b2e48SStefano Zampini     if (pcbddc->benign_change) {
16229566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcbddc->benign_B0));
1623c263805aSStefano Zampini       /* pop B0 from pcbddc->local_mat */
16249566063dSJacob Faibussowitsch       PetscCall(PCBDDCBenignPopOrPushB0(pc, PETSC_TRUE));
1625c263805aSStefano Zampini     }
16265e8657edSStefano Zampini     /* get submatrices */
16279566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_IB));
16289566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_BI));
16299566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_BB));
16309566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_B_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &pcis->A_BB));
16319566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_I_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &pcis->A_IB));
16329566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_B_local, pcis->is_I_local, MAT_INITIAL_MATRIX, &pcis->A_BI));
16333975b054SStefano Zampini     /* set flag in pcis to not reuse submatrices during PCISCreate */
16343975b054SStefano Zampini     pcis->reusesubmatrices = PETSC_FALSE;
16359c6a02ceSStefano Zampini   } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) {
16369566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcbddc->local_mat));
16379566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)matis->A));
16385e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
16395e8657edSStefano Zampini   }
164035509ce9Sstefano_zampini 
164135509ce9Sstefano_zampini   /* interface pressure block row for B_C */
16429566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lP", (PetscObject *)&lP));
16439566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lA", (PetscObject *)&lA));
164435509ce9Sstefano_zampini   if (lA && lP) {
164535509ce9Sstefano_zampini     PC_IS    *pcis = (PC_IS *)pc->data;
164635509ce9Sstefano_zampini     Mat       B_BI, B_BB, Bt_BI, Bt_BB;
164735509ce9Sstefano_zampini     PetscBool issym;
1648b94d7dedSBarry Smith 
16499566063dSJacob Faibussowitsch     PetscCall(MatIsSymmetric(lA, PETSC_SMALL, &issym));
16506cc1294bSstefano_zampini     if (issym) {
16519566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_I_local, MAT_INITIAL_MATRIX, &B_BI));
16529566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_B_local, MAT_INITIAL_MATRIX, &B_BB));
16539566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(B_BI, &Bt_BI));
16549566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(B_BB, &Bt_BB));
165535509ce9Sstefano_zampini     } else {
16569566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_I_local, MAT_INITIAL_MATRIX, &B_BI));
16579566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_B_local, MAT_INITIAL_MATRIX, &B_BB));
16589566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, pcis->is_I_local, lP, MAT_INITIAL_MATRIX, &Bt_BI));
16599566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, pcis->is_B_local, lP, MAT_INITIAL_MATRIX, &Bt_BB));
166035509ce9Sstefano_zampini     }
16619566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_B_BI", (PetscObject)B_BI));
16629566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_B_BB", (PetscObject)B_BB));
16639566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_Bt_BI", (PetscObject)Bt_BI));
16649566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_Bt_BB", (PetscObject)Bt_BB));
16659566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B_BI));
16669566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B_BB));
16679566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Bt_BI));
16689566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Bt_BB));
166935509ce9Sstefano_zampini   }
16709566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_LocalWork[pcbddc->current_level], pc, 0, 0, 0));
167135509ce9Sstefano_zampini 
1672b96c3477SStefano Zampini   /* SetUp coarse and local Neumann solvers */
16739566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetUpSolvers(pc));
1674b96c3477SStefano Zampini   /* SetUp Scaling operator */
16751baa6e33SBarry Smith   if (pcbddc->use_deluxe_scaling) PetscCall(PCBDDCScalingSetUp(pc));
1676c703fcc7SStefano Zampini 
16771dd7afcfSStefano Zampini   /* mark topography as done */
167856282151SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
16790369aaf7SStefano Zampini 
16801dd7afcfSStefano Zampini   /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */
16819566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignShellMat(pc, PETSC_FALSE));
16821dd7afcfSStefano Zampini 
168358a03d70SStefano Zampini   if (pcbddc->dbg_flag) {
16849566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISubtractTab(pcbddc->dbg_viewer, 2 * pcbddc->current_level));
16859566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer));
16862b510759SStefano Zampini   }
16870c7d97c5SJed Brown   PetscFunctionReturn(0);
16880c7d97c5SJed Brown }
16890c7d97c5SJed Brown 
16900c7d97c5SJed Brown /*
169150efa1b5SStefano Zampini    PCApply_BDDC - Applies the BDDC operator to a vector.
16920c7d97c5SJed Brown 
16930c7d97c5SJed Brown    Input Parameters:
16940f202f7eSStefano Zampini +  pc - the preconditioner context
16950f202f7eSStefano Zampini -  r - input vector (global)
16960c7d97c5SJed Brown 
16970c7d97c5SJed Brown    Output Parameter:
16980c7d97c5SJed Brown .  z - output vector (global)
16990c7d97c5SJed Brown 
17000c7d97c5SJed Brown    Application Interface Routine: PCApply()
17010c7d97c5SJed Brown  */
17029371c9d4SSatish Balay PetscErrorCode PCApply_BDDC(PC pc, Vec r, Vec z) {
17030c7d97c5SJed Brown   PC_IS            *pcis   = (PC_IS *)(pc->data);
17040c7d97c5SJed Brown   PC_BDDC          *pcbddc = (PC_BDDC *)(pc->data);
1705b3338236SStefano Zampini   Mat               lA     = NULL;
1706b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
17073b03a366Sstefano_zampini   const PetscScalar one   = 1.0;
17083b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
17092617d88aSStefano Zampini   const PetscScalar zero  = 0.0;
17100c7d97c5SJed Brown   /* This code is similar to that provided in nn.c for PCNN
17110c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
1712b097fa66SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */
17130c7d97c5SJed Brown 
17140c7d97c5SJed Brown   PetscFunctionBegin;
17159566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(citation, &cited));
171648a46eb9SPierre Jolivet   if (pcbddc->switch_static) PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat, &lA));
1717b3338236SStefano Zampini 
17181dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
17191dd7afcfSStefano Zampini     Vec swap;
172027b6a85dSStefano Zampini 
17219566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, r, pcbddc->work_change));
17221dd7afcfSStefano Zampini     swap                = pcbddc->work_change;
17231dd7afcfSStefano Zampini     pcbddc->work_change = r;
17241dd7afcfSStefano Zampini     r                   = swap;
17251dd7afcfSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
17269cc2a9b1Sstefano_zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) {
17279566063dSJacob Faibussowitsch       PetscCall(VecCopy(r, pcis->vec1_global));
17289566063dSJacob Faibussowitsch       PetscCall(VecLockReadPush(pcis->vec1_global));
17291dd7afcfSStefano Zampini     }
17301dd7afcfSStefano Zampini   }
173127b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
17329566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, r, PETSC_TRUE));
1733efc2fbd9SStefano Zampini   }
1734bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET && !pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
17359566063dSJacob Faibussowitsch     PetscCall(VecCopy(r, z));
17360c7d97c5SJed Brown     /* First Dirichlet solve */
17379566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
17389566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
17390c7d97c5SJed Brown     /*
17400c7d97c5SJed Brown       Assembling right hand side for BDDC operator
1741b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
1742674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
17430c7d97c5SJed Brown     */
1744b097fa66SStefano Zampini     if (n_D) {
17459566063dSJacob Faibussowitsch       PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
17469566063dSJacob Faibussowitsch       PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D));
17479566063dSJacob Faibussowitsch       PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
17489566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D));
17499566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec2_D, m_one));
175016909a7fSStefano Zampini       if (pcbddc->switch_static) {
17519566063dSJacob Faibussowitsch         PetscCall(VecSet(pcis->vec1_N, 0.));
17529566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
17539566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
175416909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
17559566063dSJacob Faibussowitsch           PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N));
175616909a7fSStefano Zampini         } else {
17579566063dSJacob Faibussowitsch           PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
17589566063dSJacob Faibussowitsch           PetscCall(MatMult(lA, pcis->vec2_N, pcis->vec1_N));
17599566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
176016909a7fSStefano Zampini         }
17619566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD));
17629566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD));
17639566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
17649566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
176516909a7fSStefano Zampini       } else {
17669566063dSJacob Faibussowitsch         PetscCall(MatMult(pcis->A_BI, pcis->vec2_D, pcis->vec1_B));
176716909a7fSStefano Zampini       }
1768b097fa66SStefano Zampini     } else {
17699566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_B, zero));
1770b097fa66SStefano Zampini     }
17719566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE));
17729566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE));
17739566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingRestriction(pc, z, pcis->vec1_B));
1774b76ba322SStefano Zampini   } else {
177548a46eb9SPierre Jolivet     if (!pcbddc->benign_apply_coarse_only) PetscCall(PCBDDCScalingRestriction(pc, r, pcis->vec1_B));
17764fee134fSStefano Zampini   }
1777bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) {
177828b400f6SJacob Faibussowitsch     PetscCheck(pcbddc->switch_static, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "You forgot to pass -pc_bddc_switch_static");
17799566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
17809566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
1781bc960bbfSJed Brown   }
1782b76ba322SStefano Zampini 
17832617d88aSStefano Zampini   /* Apply interface preconditioner
17842617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
17859566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(pc, PETSC_FALSE));
17862617d88aSStefano Zampini 
1787674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
17889566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(pc, pcis->vec1_B, z));
1789bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) {
17909566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_D, z, INSERT_VALUES, SCATTER_REVERSE));
17919566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_D, z, INSERT_VALUES, SCATTER_REVERSE));
1792bc960bbfSJed Brown     PetscFunctionReturn(0);
1793bc960bbfSJed Brown   }
17943b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
17959566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
17969566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
1797b097fa66SStefano Zampini   if (n_B) {
179816909a7fSStefano Zampini     if (pcbddc->switch_static) {
17999566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
18009566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
18019566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
18029566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
180316909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
18049566063dSJacob Faibussowitsch         PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N));
180516909a7fSStefano Zampini       } else {
18069566063dSJacob Faibussowitsch         PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
18079566063dSJacob Faibussowitsch         PetscCall(MatMult(lA, pcis->vec2_N, pcis->vec1_N));
18089566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
180916909a7fSStefano Zampini       }
18109566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD));
18119566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD));
181216909a7fSStefano Zampini     } else {
18139566063dSJacob Faibussowitsch       PetscCall(MatMult(pcis->A_IB, pcis->vec1_B, pcis->vec3_D));
181416909a7fSStefano Zampini     }
181516909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
181616909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
18179566063dSJacob Faibussowitsch       PetscCall(MatMult(lA, pcis->vec1_D, pcis->vec3_D));
181816909a7fSStefano Zampini     } else {
18199566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_D, pcis->vec1_N));
18209566063dSJacob Faibussowitsch       PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N));
18219566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec2_N, pcis->vec3_D));
182216909a7fSStefano Zampini     }
1823b097fa66SStefano Zampini   }
18249566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
18259566063dSJacob Faibussowitsch   PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec3_D, pcis->vec4_D));
18269566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
18279566063dSJacob Faibussowitsch   PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec4_D));
1828efc2fbd9SStefano Zampini 
18298ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1830b097fa66SStefano Zampini     if (pcbddc->switch_static) {
18319566063dSJacob Faibussowitsch       PetscCall(VecAXPBYPCZ(pcis->vec2_D, m_one, one, m_one, pcis->vec4_D, pcis->vec1_D));
1832b097fa66SStefano Zampini     } else {
18339566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec2_D, m_one, m_one, pcis->vec4_D));
1834b097fa66SStefano Zampini     }
18359566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE));
18369566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE));
1837b097fa66SStefano Zampini   } else {
1838b097fa66SStefano Zampini     if (pcbddc->switch_static) {
18399566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec4_D, one, m_one, pcis->vec1_D));
1840b097fa66SStefano Zampini     } else {
18419566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec4_D, m_one));
1842b097fa66SStefano Zampini     }
18439566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE));
18449566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE));
1845b097fa66SStefano Zampini   }
184627b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
18471baa6e33SBarry Smith     if (pcbddc->benign_apply_coarse_only) PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n));
18489566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, z, PETSC_FALSE));
1849efc2fbd9SStefano Zampini   }
18501f4df5f7SStefano Zampini 
18511dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1852f913dca9SStefano Zampini     pcbddc->work_change = r;
18539566063dSJacob Faibussowitsch     PetscCall(VecCopy(z, pcbddc->work_change));
18549566063dSJacob Faibussowitsch     PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcbddc->work_change, z));
18551dd7afcfSStefano Zampini   }
18560c7d97c5SJed Brown   PetscFunctionReturn(0);
18570c7d97c5SJed Brown }
185850efa1b5SStefano Zampini 
185950efa1b5SStefano Zampini /*
186050efa1b5SStefano Zampini    PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector.
186150efa1b5SStefano Zampini 
186250efa1b5SStefano Zampini    Input Parameters:
18630f202f7eSStefano Zampini +  pc - the preconditioner context
18640f202f7eSStefano Zampini -  r - input vector (global)
186550efa1b5SStefano Zampini 
186650efa1b5SStefano Zampini    Output Parameter:
186750efa1b5SStefano Zampini .  z - output vector (global)
186850efa1b5SStefano Zampini 
186950efa1b5SStefano Zampini    Application Interface Routine: PCApplyTranspose()
187050efa1b5SStefano Zampini  */
18719371c9d4SSatish Balay PetscErrorCode PCApplyTranspose_BDDC(PC pc, Vec r, Vec z) {
187250efa1b5SStefano Zampini   PC_IS            *pcis   = (PC_IS *)(pc->data);
187350efa1b5SStefano Zampini   PC_BDDC          *pcbddc = (PC_BDDC *)(pc->data);
1874b3338236SStefano Zampini   Mat               lA     = NULL;
1875b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
187650efa1b5SStefano Zampini   const PetscScalar one   = 1.0;
187750efa1b5SStefano Zampini   const PetscScalar m_one = -1.0;
187850efa1b5SStefano Zampini   const PetscScalar zero  = 0.0;
187950efa1b5SStefano Zampini 
188050efa1b5SStefano Zampini   PetscFunctionBegin;
18819566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(citation, &cited));
188248a46eb9SPierre Jolivet   if (pcbddc->switch_static) PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat, &lA));
18831dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
18841dd7afcfSStefano Zampini     Vec swap;
188527b6a85dSStefano Zampini 
18869566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, r, pcbddc->work_change));
18871dd7afcfSStefano Zampini     swap                = pcbddc->work_change;
18881dd7afcfSStefano Zampini     pcbddc->work_change = r;
18891dd7afcfSStefano Zampini     r                   = swap;
189027b6a85dSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
18918ae0ca82SStefano Zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->exact_dirichlet_trick_app && pcbddc->change_interior) {
18929566063dSJacob Faibussowitsch       PetscCall(VecCopy(r, pcis->vec1_global));
18939566063dSJacob Faibussowitsch       PetscCall(VecLockReadPush(pcis->vec1_global));
18941dd7afcfSStefano Zampini     }
189527b6a85dSStefano Zampini   }
189627b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
18979566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, r, PETSC_TRUE));
1898537c1cdfSStefano Zampini   }
18998ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
19009566063dSJacob Faibussowitsch     PetscCall(VecCopy(r, z));
190150efa1b5SStefano Zampini     /* First Dirichlet solve */
19029566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
19039566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
190450efa1b5SStefano Zampini     /*
190550efa1b5SStefano Zampini       Assembling right hand side for BDDC operator
1906b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
190750efa1b5SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
190850efa1b5SStefano Zampini     */
1909b097fa66SStefano Zampini     if (n_D) {
19109566063dSJacob Faibussowitsch       PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
19119566063dSJacob Faibussowitsch       PetscCall(KSPSolveTranspose(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D));
19129566063dSJacob Faibussowitsch       PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
19139566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D));
19149566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec2_D, m_one));
191516909a7fSStefano Zampini       if (pcbddc->switch_static) {
19169566063dSJacob Faibussowitsch         PetscCall(VecSet(pcis->vec1_N, 0.));
19179566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
19189566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
191916909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
19209566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N));
192116909a7fSStefano Zampini         } else {
19229566063dSJacob Faibussowitsch           PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
19239566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(lA, pcis->vec2_N, pcis->vec1_N));
19249566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
192516909a7fSStefano Zampini         }
19269566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD));
19279566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD));
19289566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
19299566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
193016909a7fSStefano Zampini       } else {
19319566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcis->A_IB, pcis->vec2_D, pcis->vec1_B));
193216909a7fSStefano Zampini       }
1933b097fa66SStefano Zampini     } else {
19349566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_B, zero));
1935b097fa66SStefano Zampini     }
19369566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE));
19379566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE));
19389566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingRestriction(pc, z, pcis->vec1_B));
193950efa1b5SStefano Zampini   } else {
19409566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingRestriction(pc, r, pcis->vec1_B));
194150efa1b5SStefano Zampini   }
194250efa1b5SStefano Zampini 
194350efa1b5SStefano Zampini   /* Apply interface preconditioner
194450efa1b5SStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
19459566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(pc, PETSC_TRUE));
194650efa1b5SStefano Zampini 
194750efa1b5SStefano Zampini   /* Apply transpose of partition of unity operator */
19489566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(pc, pcis->vec1_B, z));
194950efa1b5SStefano Zampini 
195050efa1b5SStefano Zampini   /* Second Dirichlet solve and assembling of output */
19519566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
19529566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
1953b097fa66SStefano Zampini   if (n_B) {
195416909a7fSStefano Zampini     if (pcbddc->switch_static) {
19559566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
19569566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
19579566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
19589566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
195916909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
19609566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N));
196116909a7fSStefano Zampini       } else {
19629566063dSJacob Faibussowitsch         PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
19639566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(lA, pcis->vec2_N, pcis->vec1_N));
19649566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
196516909a7fSStefano Zampini       }
19669566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD));
19679566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD));
196816909a7fSStefano Zampini     } else {
19699566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcis->A_BI, pcis->vec1_B, pcis->vec3_D));
197016909a7fSStefano Zampini     }
197116909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
197216909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
19739566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(lA, pcis->vec1_D, pcis->vec3_D));
197416909a7fSStefano Zampini     } else {
19759566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_D, pcis->vec1_N));
19769566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N));
19779566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec2_N, pcis->vec3_D));
197816909a7fSStefano Zampini     }
1979b097fa66SStefano Zampini   }
19809566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
19819566063dSJacob Faibussowitsch   PetscCall(KSPSolveTranspose(pcbddc->ksp_D, pcis->vec3_D, pcis->vec4_D));
19829566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
19839566063dSJacob Faibussowitsch   PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec4_D));
19848ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1985b097fa66SStefano Zampini     if (pcbddc->switch_static) {
19869566063dSJacob Faibussowitsch       PetscCall(VecAXPBYPCZ(pcis->vec2_D, m_one, one, m_one, pcis->vec4_D, pcis->vec1_D));
1987b097fa66SStefano Zampini     } else {
19889566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec2_D, m_one, m_one, pcis->vec4_D));
1989b097fa66SStefano Zampini     }
19909566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE));
19919566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE));
1992b097fa66SStefano Zampini   } else {
1993b097fa66SStefano Zampini     if (pcbddc->switch_static) {
19949566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec4_D, one, m_one, pcis->vec1_D));
1995b097fa66SStefano Zampini     } else {
19969566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec4_D, m_one));
1997b097fa66SStefano Zampini     }
19989566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE));
19999566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE));
2000b097fa66SStefano Zampini   }
200127b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
20029566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, z, PETSC_FALSE));
2003537c1cdfSStefano Zampini   }
20041dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2005f913dca9SStefano Zampini     pcbddc->work_change = r;
20069566063dSJacob Faibussowitsch     PetscCall(VecCopy(z, pcbddc->work_change));
20079566063dSJacob Faibussowitsch     PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcbddc->work_change, z));
20081dd7afcfSStefano Zampini   }
200950efa1b5SStefano Zampini   PetscFunctionReturn(0);
201050efa1b5SStefano Zampini }
2011674ae819SStefano Zampini 
20129371c9d4SSatish Balay PetscErrorCode PCReset_BDDC(PC pc) {
2013da1bb401SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
20149326c5c6Sstefano_zampini   PC_IS   *pcis   = (PC_IS *)pc->data;
20159326c5c6Sstefano_zampini   KSP      kspD, kspR, kspC;
2016da1bb401SStefano Zampini 
2017da1bb401SStefano Zampini   PetscFunctionBegin;
2018674ae819SStefano Zampini   /* free BDDC custom data  */
20199566063dSJacob Faibussowitsch   PetscCall(PCBDDCResetCustomization(pc));
2020674ae819SStefano Zampini   /* destroy objects related to topography */
20219566063dSJacob Faibussowitsch   PetscCall(PCBDDCResetTopography(pc));
202234a97f8cSStefano Zampini   /* destroy objects for scaling operator */
20239566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingDestroy(pc));
2024674ae819SStefano Zampini   /* free solvers stuff */
20259566063dSJacob Faibussowitsch   PetscCall(PCBDDCResetSolvers(pc));
202662a6ff1dSStefano Zampini   /* free global vectors needed in presolve */
20279566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->temp_solution));
20289566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->original_rhs));
20291dd7afcfSStefano Zampini   /* free data created by PCIS */
20309566063dSJacob Faibussowitsch   PetscCall(PCISDestroy(pc));
20319326c5c6Sstefano_zampini 
20329326c5c6Sstefano_zampini   /* restore defaults */
20339326c5c6Sstefano_zampini   kspD = pcbddc->ksp_D;
20349326c5c6Sstefano_zampini   kspR = pcbddc->ksp_R;
20359326c5c6Sstefano_zampini   kspC = pcbddc->coarse_ksp;
20369566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(pc->data, sizeof(*pcbddc)));
20379326c5c6Sstefano_zampini   pcis->n_neigh                     = -1;
20389326c5c6Sstefano_zampini   pcis->scaling_factor              = 1.0;
20399326c5c6Sstefano_zampini   pcis->reusesubmatrices            = PETSC_TRUE;
20409326c5c6Sstefano_zampini   pcbddc->use_local_adj             = PETSC_TRUE;
20419326c5c6Sstefano_zampini   pcbddc->use_vertices              = PETSC_TRUE;
20429326c5c6Sstefano_zampini   pcbddc->use_edges                 = PETSC_TRUE;
20439326c5c6Sstefano_zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
20449326c5c6Sstefano_zampini   pcbddc->vertex_size               = 1;
20459326c5c6Sstefano_zampini   pcbddc->recompute_topography      = PETSC_TRUE;
20469326c5c6Sstefano_zampini   pcbddc->coarse_size               = -1;
20479326c5c6Sstefano_zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
20489326c5c6Sstefano_zampini   pcbddc->coarsening_ratio          = 8;
20499326c5c6Sstefano_zampini   pcbddc->coarse_eqs_per_proc       = 1;
20509326c5c6Sstefano_zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
20519326c5c6Sstefano_zampini   pcbddc->nedfield                  = -1;
20529326c5c6Sstefano_zampini   pcbddc->nedglobal                 = PETSC_TRUE;
20539326c5c6Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
20549326c5c6Sstefano_zampini   pcbddc->sub_schurs_layers         = -1;
20559326c5c6Sstefano_zampini   pcbddc->ksp_D                     = kspD;
20569326c5c6Sstefano_zampini   pcbddc->ksp_R                     = kspR;
20579326c5c6Sstefano_zampini   pcbddc->coarse_ksp                = kspC;
20589326c5c6Sstefano_zampini   PetscFunctionReturn(0);
20599326c5c6Sstefano_zampini }
20609326c5c6Sstefano_zampini 
20619371c9d4SSatish Balay PetscErrorCode PCDestroy_BDDC(PC pc) {
20629326c5c6Sstefano_zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
20639326c5c6Sstefano_zampini 
20649326c5c6Sstefano_zampini   PetscFunctionBegin;
20659566063dSJacob Faibussowitsch   PetscCall(PCReset_BDDC(pc));
20669566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcbddc->ksp_D));
20679566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcbddc->ksp_R));
20689566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcbddc->coarse_ksp));
20699566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDiscreteGradient_C", NULL));
20709566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDivergenceMat_C", NULL));
20719566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetChangeOfBasisMat_C", NULL));
20729566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesLocalIS_C", NULL));
20739566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesIS_C", NULL));
207432fe681dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesLocalIS_C", NULL));
207532fe681dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesIS_C", NULL));
20769566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetCoarseningRatio_C", NULL));
20779566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevel_C", NULL));
20789566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetUseExactDirichlet_C", NULL));
20799566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevels_C", NULL));
20809566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundaries_C", NULL));
20819566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundariesLocal_C", NULL));
20829566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundaries_C", NULL));
20839566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundariesLocal_C", NULL));
20849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundaries_C", NULL));
20859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundariesLocal_C", NULL));
20869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundaries_C", NULL));
20879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundariesLocal_C", NULL));
20889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplitting_C", NULL));
20899566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplittingLocal_C", NULL));
20909566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", NULL));
20919566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCCreateFETIDPOperators_C", NULL));
20929566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetRHS_C", NULL));
20939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetSolution_C", NULL));
20949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", NULL));
20959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", NULL));
20969566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
2097da1bb401SStefano Zampini   PetscFunctionReturn(0);
2098da1bb401SStefano Zampini }
20991e6b0712SBarry Smith 
21009371c9d4SSatish Balay static PetscErrorCode PCSetCoordinates_BDDC(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords) {
2101ab8c8b98SStefano Zampini   PC_BDDC    *pcbddc    = (PC_BDDC *)pc->data;
2102ab8c8b98SStefano Zampini   PCBDDCGraph mat_graph = pcbddc->mat_graph;
2103ab8c8b98SStefano Zampini 
2104ab8c8b98SStefano Zampini   PetscFunctionBegin;
21059566063dSJacob Faibussowitsch   PetscCall(PetscFree(mat_graph->coords));
21069566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nloc * dim, &mat_graph->coords));
21079566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(mat_graph->coords, coords, nloc * dim));
2108ab8c8b98SStefano Zampini   mat_graph->cnloc             = nloc;
2109ab8c8b98SStefano Zampini   mat_graph->cdim              = dim;
2110ab8c8b98SStefano Zampini   mat_graph->cloc              = PETSC_FALSE;
21114f819b78SStefano Zampini   /* flg setup */
21124f819b78SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
21134f819b78SStefano Zampini   pcbddc->corner_selected      = PETSC_FALSE;
2114ab8c8b98SStefano Zampini   PetscFunctionReturn(0);
2115ab8c8b98SStefano Zampini }
2116ab8c8b98SStefano Zampini 
21179371c9d4SSatish Balay static PetscErrorCode PCPreSolveChangeRHS_BDDC(PC pc, PetscBool *change) {
2118a06fd7f2SStefano Zampini   PetscFunctionBegin;
2119a06fd7f2SStefano Zampini   *change = PETSC_TRUE;
2120a06fd7f2SStefano Zampini   PetscFunctionReturn(0);
2121a06fd7f2SStefano Zampini }
2122a06fd7f2SStefano Zampini 
21239371c9d4SSatish Balay static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) {
2124674ae819SStefano Zampini   FETIDPMat_ctx mat_ctx;
2125266e20e9SStefano Zampini   Vec           work;
21263425bc38SStefano Zampini   PC_IS        *pcis;
21273425bc38SStefano Zampini   PC_BDDC      *pcbddc;
21280c7d97c5SJed Brown 
21293425bc38SStefano Zampini   PetscFunctionBegin;
21309566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx));
21313425bc38SStefano Zampini   pcis   = (PC_IS *)mat_ctx->pc->data;
21323425bc38SStefano Zampini   pcbddc = (PC_BDDC *)mat_ctx->pc->data;
21333425bc38SStefano Zampini 
21349566063dSJacob Faibussowitsch   PetscCall(VecSet(fetidp_flux_rhs, 0.0));
2135229984c5Sstefano_zampini   /* copy rhs since we may change it during PCPreSolve_BDDC */
213648a46eb9SPierre Jolivet   if (!pcbddc->original_rhs) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->original_rhs));
21376cc1294bSstefano_zampini   if (mat_ctx->rhs_flip) {
21389566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(pcbddc->original_rhs, standard_rhs, mat_ctx->rhs_flip));
21396cc1294bSstefano_zampini   } else {
21409566063dSJacob Faibussowitsch     PetscCall(VecCopy(standard_rhs, pcbddc->original_rhs));
21416cc1294bSstefano_zampini   }
2142af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
2143229984c5Sstefano_zampini     /* interface pressure rhs */
21449566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->g2g_p, fetidp_flux_rhs, pcbddc->original_rhs, INSERT_VALUES, SCATTER_REVERSE));
21459566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->g2g_p, fetidp_flux_rhs, pcbddc->original_rhs, INSERT_VALUES, SCATTER_REVERSE));
21469566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->g2g_p, standard_rhs, fetidp_flux_rhs, INSERT_VALUES, SCATTER_FORWARD));
21479566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->g2g_p, standard_rhs, fetidp_flux_rhs, INSERT_VALUES, SCATTER_FORWARD));
214848a46eb9SPierre Jolivet     if (!mat_ctx->rhs_flip) PetscCall(VecScale(fetidp_flux_rhs, -1.));
21496cc1294bSstefano_zampini   }
2150c08af4c6SStefano Zampini   /*
2151c08af4c6SStefano Zampini      change of basis for physical rhs if needed
2152c08af4c6SStefano Zampini      It also changes the rhs in case of dirichlet boundaries
2153c08af4c6SStefano Zampini   */
21549566063dSJacob Faibussowitsch   PetscCall(PCPreSolve_BDDC(mat_ctx->pc, NULL, pcbddc->original_rhs, NULL));
2155fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
21569566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, pcbddc->original_rhs, pcbddc->work_change));
21573738a8e6SStefano Zampini     work = pcbddc->work_change;
2158fc17d649SStefano Zampini   } else {
21593738a8e6SStefano Zampini     work = pcbddc->original_rhs;
2160fc17d649SStefano Zampini   }
21613425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
21629566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_D, work, mat_ctx->temp_solution_D, INSERT_VALUES, SCATTER_FORWARD));
21639566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_D, work, mat_ctx->temp_solution_D, INSERT_VALUES, SCATTER_FORWARD));
2164fb223d50SStefano Zampini   /* scale rhs since it should be unassembled */
2165fb223d50SStefano Zampini   /* TODO use counter scaling? (also below) */
21669566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD));
21679566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD));
2168674ae819SStefano Zampini   /* Apply partition of unity */
21699566063dSJacob Faibussowitsch   PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B, pcis->D, mat_ctx->temp_solution_B));
21709566063dSJacob Faibussowitsch   /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */
21718eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
21723425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
21739566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0));
21749566063dSJacob Faibussowitsch     PetscCall(KSPSolve(pcbddc->ksp_D, mat_ctx->temp_solution_D, pcis->vec1_D));
21759566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0));
2176c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
21779566063dSJacob Faibussowitsch     PetscCall(MatMult(pcis->A_BI, pcis->vec1_D, pcis->vec1_B));
21789566063dSJacob Faibussowitsch     PetscCall(VecAXPY(mat_ctx->temp_solution_B, -1.0, pcis->vec1_B));
21799566063dSJacob Faibussowitsch     PetscCall(VecSet(work, 0.0));
21809566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, mat_ctx->temp_solution_B, work, ADD_VALUES, SCATTER_REVERSE));
21819566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, mat_ctx->temp_solution_B, work, ADD_VALUES, SCATTER_REVERSE));
21829566063dSJacob Faibussowitsch     /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */
21839566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD));
21849566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD));
21859566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B, pcis->D, mat_ctx->temp_solution_B));
21863425bc38SStefano Zampini   }
21873425bc38SStefano Zampini   /* BDDC rhs */
21889566063dSJacob Faibussowitsch   PetscCall(VecCopy(mat_ctx->temp_solution_B, pcis->vec1_B));
21891baa6e33SBarry Smith   if (pcbddc->switch_static) PetscCall(VecCopy(mat_ctx->temp_solution_D, pcis->vec1_D));
21903425bc38SStefano Zampini   /* apply BDDC */
21919566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n));
21929566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc, PETSC_FALSE));
21939566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n));
2194229984c5Sstefano_zampini 
21953425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
21969566063dSJacob Faibussowitsch   PetscCall(MatMult(mat_ctx->B_delta, pcis->vec1_B, mat_ctx->lambda_local));
21979566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(mat_ctx->l2g_lambda, mat_ctx->lambda_local, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD));
21989566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(mat_ctx->l2g_lambda, mat_ctx->lambda_local, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD));
2199229984c5Sstefano_zampini   /* Add contribution to interface pressures */
2200229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
22019566063dSJacob Faibussowitsch     PetscCall(MatMult(mat_ctx->B_BB, pcis->vec1_B, mat_ctx->vP));
22021baa6e33SBarry Smith     if (pcbddc->switch_static) PetscCall(MatMultAdd(mat_ctx->B_BI, pcis->vec1_D, mat_ctx->vP, mat_ctx->vP));
22039566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->l2g_p, mat_ctx->vP, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD));
22049566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->l2g_p, mat_ctx->vP, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD));
2205229984c5Sstefano_zampini   }
22063425bc38SStefano Zampini   PetscFunctionReturn(0);
22073425bc38SStefano Zampini }
22081e6b0712SBarry Smith 
22093425bc38SStefano Zampini /*@
22100f202f7eSStefano Zampini    PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side
22113425bc38SStefano Zampini 
22123425bc38SStefano Zampini    Collective
22133425bc38SStefano Zampini 
22143425bc38SStefano Zampini    Input Parameters:
2215*f1580f4eSBarry Smith +  fetidp_mat      - the FETI-DP matrix object obtained by a call to `PCBDDCCreateFETIDPOperators()`
22160f202f7eSStefano Zampini -  standard_rhs    - the right-hand side of the original linear system
22173425bc38SStefano Zampini 
2218*f1580f4eSBarry Smith    Output Parameter:
22190f202f7eSStefano Zampini .  fetidp_flux_rhs - the right-hand side for the FETI-DP linear system
22203425bc38SStefano Zampini 
22213425bc38SStefano Zampini    Level: developer
22223425bc38SStefano Zampini 
222316b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCCreateFETIDPOperators()`, `PCBDDCMatFETIDPGetSolution()`
22243425bc38SStefano Zampini @*/
22259371c9d4SSatish Balay PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs) {
2226674ae819SStefano Zampini   FETIDPMat_ctx mat_ctx;
22273425bc38SStefano Zampini 
22283425bc38SStefano Zampini   PetscFunctionBegin;
2229266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat, MAT_CLASSID, 1);
2230266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_rhs, VEC_CLASSID, 2);
2231266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_rhs, VEC_CLASSID, 3);
22329566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx));
2233cac4c232SBarry Smith   PetscUseMethod(mat_ctx->pc, "PCBDDCMatFETIDPGetRHS_C", (Mat, Vec, Vec), (fetidp_mat, standard_rhs, fetidp_flux_rhs));
22343425bc38SStefano Zampini   PetscFunctionReturn(0);
22353425bc38SStefano Zampini }
22361e6b0712SBarry Smith 
22379371c9d4SSatish Balay static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) {
2238674ae819SStefano Zampini   FETIDPMat_ctx mat_ctx;
22393425bc38SStefano Zampini   PC_IS        *pcis;
22403425bc38SStefano Zampini   PC_BDDC      *pcbddc;
2241229984c5Sstefano_zampini   Vec           work;
22423425bc38SStefano Zampini 
22433425bc38SStefano Zampini   PetscFunctionBegin;
22449566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx));
22453425bc38SStefano Zampini   pcis   = (PC_IS *)mat_ctx->pc->data;
22463425bc38SStefano Zampini   pcbddc = (PC_BDDC *)mat_ctx->pc->data;
22473425bc38SStefano Zampini 
22483425bc38SStefano Zampini   /* apply B_delta^T */
22499566063dSJacob Faibussowitsch   PetscCall(VecSet(pcis->vec1_B, 0.));
22509566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(mat_ctx->l2g_lambda, fetidp_flux_sol, mat_ctx->lambda_local, INSERT_VALUES, SCATTER_REVERSE));
22519566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(mat_ctx->l2g_lambda, fetidp_flux_sol, mat_ctx->lambda_local, INSERT_VALUES, SCATTER_REVERSE));
22529566063dSJacob Faibussowitsch   PetscCall(MatMultTranspose(mat_ctx->B_delta, mat_ctx->lambda_local, pcis->vec1_B));
2253229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
22549566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->l2g_p, fetidp_flux_sol, mat_ctx->vP, INSERT_VALUES, SCATTER_REVERSE));
22559566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->l2g_p, fetidp_flux_sol, mat_ctx->vP, INSERT_VALUES, SCATTER_REVERSE));
22569566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(mat_ctx->Bt_BB, mat_ctx->vP, pcis->vec1_B, pcis->vec1_B));
2257229984c5Sstefano_zampini   }
2258229984c5Sstefano_zampini 
22593425bc38SStefano Zampini   /* compute rhs for BDDC application */
22609566063dSJacob Faibussowitsch   PetscCall(VecAYPX(pcis->vec1_B, -1.0, mat_ctx->temp_solution_B));
22618eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
22629566063dSJacob Faibussowitsch     PetscCall(VecCopy(mat_ctx->temp_solution_D, pcis->vec1_D));
2263229984c5Sstefano_zampini     if (mat_ctx->l2g_p) {
22649566063dSJacob Faibussowitsch       PetscCall(VecScale(mat_ctx->vP, -1.));
22659566063dSJacob Faibussowitsch       PetscCall(MatMultAdd(mat_ctx->Bt_BI, mat_ctx->vP, pcis->vec1_D, pcis->vec1_D));
22663425bc38SStefano Zampini     }
2267229984c5Sstefano_zampini   }
2268229984c5Sstefano_zampini 
22693425bc38SStefano Zampini   /* apply BDDC */
22709566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n));
22719566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc, PETSC_FALSE));
2272229984c5Sstefano_zampini 
2273229984c5Sstefano_zampini   /* put values into global vector */
2274af140850Sstefano_zampini   if (pcbddc->ChangeOfBasisMatrix) work = pcbddc->work_change;
2275af140850Sstefano_zampini   else work = standard_sol;
22769566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, work, INSERT_VALUES, SCATTER_REVERSE));
22779566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, work, INSERT_VALUES, SCATTER_REVERSE));
22788eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
22793425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
22809566063dSJacob Faibussowitsch     PetscCall(MatMult(pcis->A_IB, pcis->vec1_B, pcis->vec1_D));
22819566063dSJacob Faibussowitsch     PetscCall(VecAYPX(pcis->vec1_D, -1.0, mat_ctx->temp_solution_D));
22829566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0));
22839566063dSJacob Faibussowitsch     PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec1_D));
22849566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0));
2285c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
22863425bc38SStefano Zampini   }
2287229984c5Sstefano_zampini 
22889566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_D, work, INSERT_VALUES, SCATTER_REVERSE));
22899566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_D, work, INSERT_VALUES, SCATTER_REVERSE));
2290266e20e9SStefano Zampini   /* add p0 solution to final solution */
22919566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignGetOrSetP0(mat_ctx->pc, work, PETSC_FALSE));
22921baa6e33SBarry Smith   if (pcbddc->ChangeOfBasisMatrix) PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, work, standard_sol));
22939566063dSJacob Faibussowitsch   PetscCall(PCPostSolve_BDDC(mat_ctx->pc, NULL, NULL, standard_sol));
2294af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
22959566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->g2g_p, fetidp_flux_sol, standard_sol, INSERT_VALUES, SCATTER_REVERSE));
22969566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->g2g_p, fetidp_flux_sol, standard_sol, INSERT_VALUES, SCATTER_REVERSE));
2297229984c5Sstefano_zampini   }
22983425bc38SStefano Zampini   PetscFunctionReturn(0);
22993425bc38SStefano Zampini }
23001e6b0712SBarry Smith 
23019371c9d4SSatish Balay static PetscErrorCode PCView_BDDCIPC(PC pc, PetscViewer viewer) {
23025a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
23035a1e936bSStefano Zampini   PetscBool   isascii;
23045a1e936bSStefano Zampini 
23055a1e936bSStefano Zampini   PetscFunctionBegin;
23069566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
23079566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
230848a46eb9SPierre Jolivet   if (isascii) PetscCall(PetscViewerASCIIPrintf(viewer, "BDDC interface preconditioner\n"));
23099566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushTab(viewer));
23109566063dSJacob Faibussowitsch   PetscCall(PCView(bddcipc_ctx->bddc, viewer));
23119566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopTab(viewer));
23125a1e936bSStefano Zampini   PetscFunctionReturn(0);
23135a1e936bSStefano Zampini }
23145a1e936bSStefano Zampini 
23159371c9d4SSatish Balay static PetscErrorCode PCSetUp_BDDCIPC(PC pc) {
23165a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
23175a1e936bSStefano Zampini   PetscBool   isbddc;
23185a1e936bSStefano Zampini   Vec         vv;
23195a1e936bSStefano Zampini   IS          is;
23205a1e936bSStefano Zampini   PC_IS      *pcis;
23215a1e936bSStefano Zampini 
23225a1e936bSStefano Zampini   PetscFunctionBegin;
23239566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
23249566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)bddcipc_ctx->bddc, PCBDDC, &isbddc));
232528b400f6SJacob Faibussowitsch   PetscCheck(isbddc, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Invalid type %s. Must be of type bddc", ((PetscObject)bddcipc_ctx->bddc)->type_name);
23269566063dSJacob Faibussowitsch   PetscCall(PCSetUp(bddcipc_ctx->bddc));
23275a1e936bSStefano Zampini 
23285a1e936bSStefano Zampini   /* create interface scatter */
23295a1e936bSStefano Zampini   pcis = (PC_IS *)(bddcipc_ctx->bddc->data);
23309566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l));
23319566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(pc->pmat, &vv, NULL));
23329566063dSJacob Faibussowitsch   PetscCall(ISRenumber(pcis->is_B_global, NULL, NULL, &is));
23339566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(vv, is, pcis->vec1_B, NULL, &bddcipc_ctx->g2l));
23349566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
23359566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&vv));
23365a1e936bSStefano Zampini   PetscFunctionReturn(0);
23375a1e936bSStefano Zampini }
23385a1e936bSStefano Zampini 
23399371c9d4SSatish Balay static PetscErrorCode PCApply_BDDCIPC(PC pc, Vec r, Vec x) {
23405a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
23415a1e936bSStefano Zampini   PC_IS      *pcis;
23425a1e936bSStefano Zampini   VecScatter  tmps;
23435a1e936bSStefano Zampini 
23445a1e936bSStefano Zampini   PetscFunctionBegin;
23459566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
23465a1e936bSStefano Zampini   pcis              = (PC_IS *)(bddcipc_ctx->bddc->data);
23475a1e936bSStefano Zampini   tmps              = pcis->global_to_B;
23485a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
23499566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc, r, pcis->vec1_B));
23509566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc, PETSC_FALSE));
23519566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc, pcis->vec1_B, x));
23525a1e936bSStefano Zampini   pcis->global_to_B = tmps;
23535a1e936bSStefano Zampini   PetscFunctionReturn(0);
23545a1e936bSStefano Zampini }
23555a1e936bSStefano Zampini 
23569371c9d4SSatish Balay static PetscErrorCode PCApplyTranspose_BDDCIPC(PC pc, Vec r, Vec x) {
23575a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
23585a1e936bSStefano Zampini   PC_IS      *pcis;
23595a1e936bSStefano Zampini   VecScatter  tmps;
23605a1e936bSStefano Zampini 
23615a1e936bSStefano Zampini   PetscFunctionBegin;
23629566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
23635a1e936bSStefano Zampini   pcis              = (PC_IS *)(bddcipc_ctx->bddc->data);
23645a1e936bSStefano Zampini   tmps              = pcis->global_to_B;
23655a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
23669566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc, r, pcis->vec1_B));
23679566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc, PETSC_TRUE));
23689566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc, pcis->vec1_B, x));
23695a1e936bSStefano Zampini   pcis->global_to_B = tmps;
23705a1e936bSStefano Zampini   PetscFunctionReturn(0);
23715a1e936bSStefano Zampini }
23725a1e936bSStefano Zampini 
23739371c9d4SSatish Balay static PetscErrorCode PCDestroy_BDDCIPC(PC pc) {
23745a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
23755a1e936bSStefano Zampini 
23765a1e936bSStefano Zampini   PetscFunctionBegin;
23779566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
23789566063dSJacob Faibussowitsch   PetscCall(PCDestroy(&bddcipc_ctx->bddc));
23799566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l));
23809566063dSJacob Faibussowitsch   PetscCall(PetscFree(bddcipc_ctx));
23815a1e936bSStefano Zampini   PetscFunctionReturn(0);
23825a1e936bSStefano Zampini }
23835a1e936bSStefano Zampini 
23843425bc38SStefano Zampini /*@
23850f202f7eSStefano Zampini  PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system
23863425bc38SStefano Zampini 
23873425bc38SStefano Zampini    Collective
23883425bc38SStefano Zampini 
23893425bc38SStefano Zampini    Input Parameters:
2390*f1580f4eSBarry Smith +  fetidp_mat      - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators()`
2391*f1580f4eSBarry Smith -  fetidp_flux_sol - the solution of the FETI-DP linear system`
23923425bc38SStefano Zampini 
2393*f1580f4eSBarry Smith    Output Parameter:
23940f202f7eSStefano Zampini .  standard_sol    - the solution defined on the physical domain
23953425bc38SStefano Zampini 
23963425bc38SStefano Zampini    Level: developer
23973425bc38SStefano Zampini 
239816b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCCreateFETIDPOperators()`, `PCBDDCMatFETIDPGetRHS()`
23993425bc38SStefano Zampini @*/
24009371c9d4SSatish Balay PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol) {
2401674ae819SStefano Zampini   FETIDPMat_ctx mat_ctx;
24023425bc38SStefano Zampini 
24033425bc38SStefano Zampini   PetscFunctionBegin;
2404266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat, MAT_CLASSID, 1);
2405266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_sol, VEC_CLASSID, 2);
2406266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_sol, VEC_CLASSID, 3);
24079566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx));
2408cac4c232SBarry Smith   PetscUseMethod(mat_ctx->pc, "PCBDDCMatFETIDPGetSolution_C", (Mat, Vec, Vec), (fetidp_mat, fetidp_flux_sol, standard_sol));
24093425bc38SStefano Zampini   PetscFunctionReturn(0);
24103425bc38SStefano Zampini }
24111e6b0712SBarry Smith 
24129371c9d4SSatish Balay static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc) {
2413674ae819SStefano Zampini   FETIDPMat_ctx fetidpmat_ctx;
24143425bc38SStefano Zampini   Mat           newmat;
2415674ae819SStefano Zampini   FETIDPPC_ctx  fetidppc_ctx;
24163425bc38SStefano Zampini   PC            newpc;
2417ce94432eSBarry Smith   MPI_Comm      comm;
24183425bc38SStefano Zampini 
24193425bc38SStefano Zampini   PetscFunctionBegin;
24209566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)pc, &comm));
242115579a77SStefano Zampini   /* FETI-DP matrix */
24229566063dSJacob Faibussowitsch   PetscCall(PCBDDCCreateFETIDPMatContext(pc, &fetidpmat_ctx));
24231720468bSStefano Zampini   fetidpmat_ctx->fully_redundant = fully_redundant;
24249566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetupFETIDPMatContext(fetidpmat_ctx));
24259566063dSJacob Faibussowitsch   PetscCall(MatCreateShell(comm, fetidpmat_ctx->n, fetidpmat_ctx->n, fetidpmat_ctx->N, fetidpmat_ctx->N, fetidpmat_ctx, &newmat));
24269566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)newmat, !fetidpmat_ctx->l2g_lambda_only ? "F" : "G"));
24279566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(newmat, MATOP_MULT, (void (*)(void))FETIDPMatMult));
24289566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(newmat, MATOP_MULT_TRANSPOSE, (void (*)(void))FETIDPMatMultTranspose));
24299566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(newmat, MATOP_DESTROY, (void (*)(void))PCBDDCDestroyFETIDPMat));
243015579a77SStefano Zampini   /* propagate MatOptions */
243115579a77SStefano Zampini   {
243215579a77SStefano Zampini     PC_BDDC  *pcbddc = (PC_BDDC *)fetidpmat_ctx->pc->data;
2433b94d7dedSBarry Smith     PetscBool isset, issym;
243415579a77SStefano Zampini 
2435b94d7dedSBarry Smith     PetscCall(MatIsSymmetricKnown(pc->mat, &isset, &issym));
2436b94d7dedSBarry Smith     if ((isset && issym) || pcbddc->symmetric_primal) PetscCall(MatSetOption(newmat, MAT_SYMMETRIC, PETSC_TRUE));
243715579a77SStefano Zampini   }
24389566063dSJacob Faibussowitsch   PetscCall(MatSetOptionsPrefix(newmat, prefix));
24399566063dSJacob Faibussowitsch   PetscCall(MatAppendOptionsPrefix(newmat, "fetidp_"));
24409566063dSJacob Faibussowitsch   PetscCall(MatSetUp(newmat));
244115579a77SStefano Zampini   /* FETI-DP preconditioner */
24429566063dSJacob Faibussowitsch   PetscCall(PCBDDCCreateFETIDPPCContext(pc, &fetidppc_ctx));
24439566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetupFETIDPPCContext(newmat, fetidppc_ctx));
24449566063dSJacob Faibussowitsch   PetscCall(PCCreate(comm, &newpc));
24459566063dSJacob Faibussowitsch   PetscCall(PCSetOperators(newpc, newmat, newmat));
24469566063dSJacob Faibussowitsch   PetscCall(PCSetOptionsPrefix(newpc, prefix));
24479566063dSJacob Faibussowitsch   PetscCall(PCAppendOptionsPrefix(newpc, "fetidp_"));
24489566063dSJacob Faibussowitsch   PetscCall(PCSetErrorIfFailure(newpc, pc->erroriffailure));
244915579a77SStefano Zampini   if (!fetidpmat_ctx->l2g_lambda_only) { /* standard FETI-DP */
24509566063dSJacob Faibussowitsch     PetscCall(PCSetType(newpc, PCSHELL));
24519566063dSJacob Faibussowitsch     PetscCall(PCShellSetName(newpc, "FETI-DP multipliers"));
24529566063dSJacob Faibussowitsch     PetscCall(PCShellSetContext(newpc, fetidppc_ctx));
24539566063dSJacob Faibussowitsch     PetscCall(PCShellSetApply(newpc, FETIDPPCApply));
24549566063dSJacob Faibussowitsch     PetscCall(PCShellSetApplyTranspose(newpc, FETIDPPCApplyTranspose));
24559566063dSJacob Faibussowitsch     PetscCall(PCShellSetView(newpc, FETIDPPCView));
24569566063dSJacob Faibussowitsch     PetscCall(PCShellSetDestroy(newpc, PCBDDCDestroyFETIDPPC));
24575a1e936bSStefano Zampini   } else { /* saddle-point FETI-DP */
24585a1e936bSStefano Zampini     Mat       M;
24595a1e936bSStefano Zampini     PetscInt  psize;
24605a1e936bSStefano Zampini     PetscBool fake = PETSC_FALSE, isfieldsplit;
2461e1214c54Sstefano_zampini 
24629566063dSJacob Faibussowitsch     PetscCall(ISViewFromOptions(fetidpmat_ctx->lagrange, NULL, "-lag_view"));
24639566063dSJacob Faibussowitsch     PetscCall(ISViewFromOptions(fetidpmat_ctx->pressure, NULL, "-press_view"));
24649566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_PPmat", (PetscObject *)&M));
24659566063dSJacob Faibussowitsch     PetscCall(PCSetType(newpc, PCFIELDSPLIT));
24669566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetIS(newpc, "lag", fetidpmat_ctx->lagrange));
24679566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetIS(newpc, "p", fetidpmat_ctx->pressure));
24689566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetType(newpc, PC_COMPOSITE_SCHUR));
24699566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetSchurFactType(newpc, PC_FIELDSPLIT_SCHUR_FACT_DIAG));
24709566063dSJacob Faibussowitsch     PetscCall(ISGetSize(fetidpmat_ctx->pressure, &psize));
24715a1e936bSStefano Zampini     if (psize != M->rmap->N) {
24725a1e936bSStefano Zampini       Mat      M2;
24735a1e936bSStefano Zampini       PetscInt lpsize;
24745a1e936bSStefano Zampini 
24755a1e936bSStefano Zampini       fake = PETSC_TRUE;
24769566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(fetidpmat_ctx->pressure, &lpsize));
24779566063dSJacob Faibussowitsch       PetscCall(MatCreate(comm, &M2));
24789566063dSJacob Faibussowitsch       PetscCall(MatSetType(M2, MATAIJ));
24799566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(M2, lpsize, lpsize, psize, psize));
24809566063dSJacob Faibussowitsch       PetscCall(MatSetUp(M2));
24819566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(M2, MAT_FINAL_ASSEMBLY));
24829566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(M2, MAT_FINAL_ASSEMBLY));
24839566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSetSchurPre(newpc, PC_FIELDSPLIT_SCHUR_PRE_USER, M2));
24849566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&M2));
24855a1e936bSStefano Zampini     } else {
24869566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSetSchurPre(newpc, PC_FIELDSPLIT_SCHUR_PRE_USER, M));
24875a1e936bSStefano Zampini     }
24889566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetSchurScale(newpc, 1.0));
248915579a77SStefano Zampini 
249015579a77SStefano Zampini     /* we need to setfromoptions and setup here to access the blocks */
24919566063dSJacob Faibussowitsch     PetscCall(PCSetFromOptions(newpc));
24929566063dSJacob Faibussowitsch     PetscCall(PCSetUp(newpc));
2493e1214c54Sstefano_zampini 
24945a1e936bSStefano Zampini     /* user may have changed the type (e.g. -fetidp_pc_type none) */
24959566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)newpc, PCFIELDSPLIT, &isfieldsplit));
24965a1e936bSStefano Zampini     if (isfieldsplit) {
24975a1e936bSStefano Zampini       KSP      *ksps;
24985a1e936bSStefano Zampini       PC        ppc, lagpc;
24995a1e936bSStefano Zampini       PetscInt  nn;
2500064a4176SStefano Zampini       PetscBool ismatis, matisok = PETSC_FALSE, check = PETSC_FALSE;
25015a1e936bSStefano Zampini 
2502e1214c54Sstefano_zampini       /* set the solver for the (0,0) block */
25039566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSchurGetSubKSP(newpc, &nn, &ksps));
25045a1e936bSStefano Zampini       if (!nn) { /* not of type PC_COMPOSITE_SCHUR */
25059566063dSJacob Faibussowitsch         PetscCall(PCFieldSplitGetSubKSP(newpc, &nn, &ksps));
25065a1e936bSStefano Zampini         if (!fake) { /* pass pmat to the pressure solver */
25075a1e936bSStefano Zampini           Mat F;
25085a1e936bSStefano Zampini 
25099566063dSJacob Faibussowitsch           PetscCall(KSPGetOperators(ksps[1], &F, NULL));
25109566063dSJacob Faibussowitsch           PetscCall(KSPSetOperators(ksps[1], F, M));
25115a1e936bSStefano Zampini         }
25125a1e936bSStefano Zampini       } else {
2513b94d7dedSBarry Smith         PetscBool issym, isset;
25145a1e936bSStefano Zampini         Mat       S;
25155a1e936bSStefano Zampini 
25169566063dSJacob Faibussowitsch         PetscCall(PCFieldSplitSchurGetS(newpc, &S));
2517b94d7dedSBarry Smith         PetscCall(MatIsSymmetricKnown(newmat, &isset, &issym));
2518b94d7dedSBarry Smith         if (isset) PetscCall(MatSetOption(S, MAT_SYMMETRIC, issym));
25195a1e936bSStefano Zampini       }
25209566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksps[0], &lagpc));
25219566063dSJacob Faibussowitsch       PetscCall(PCSetType(lagpc, PCSHELL));
25229566063dSJacob Faibussowitsch       PetscCall(PCShellSetName(lagpc, "FETI-DP multipliers"));
25239566063dSJacob Faibussowitsch       PetscCall(PCShellSetContext(lagpc, fetidppc_ctx));
25249566063dSJacob Faibussowitsch       PetscCall(PCShellSetApply(lagpc, FETIDPPCApply));
25259566063dSJacob Faibussowitsch       PetscCall(PCShellSetApplyTranspose(lagpc, FETIDPPCApplyTranspose));
25269566063dSJacob Faibussowitsch       PetscCall(PCShellSetView(lagpc, FETIDPPCView));
25279566063dSJacob Faibussowitsch       PetscCall(PCShellSetDestroy(lagpc, PCBDDCDestroyFETIDPPC));
25285a1e936bSStefano Zampini 
25295a1e936bSStefano Zampini       /* Olof's idea: interface Schur complement preconditioner for the mass matrix */
25309566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksps[1], &ppc));
25315a1e936bSStefano Zampini       if (fake) {
25325a1e936bSStefano Zampini         BDDCIPC_ctx    bddcipc_ctx;
2533ff11fd76SStefano Zampini         PetscContainer c;
25345a1e936bSStefano Zampini 
25355a1e936bSStefano Zampini         matisok = PETSC_TRUE;
25365a1e936bSStefano Zampini 
25375a1e936bSStefano Zampini         /* create inner BDDC solver */
25389566063dSJacob Faibussowitsch         PetscCall(PetscNew(&bddcipc_ctx));
25399566063dSJacob Faibussowitsch         PetscCall(PCCreate(comm, &bddcipc_ctx->bddc));
25409566063dSJacob Faibussowitsch         PetscCall(PCSetType(bddcipc_ctx->bddc, PCBDDC));
25419566063dSJacob Faibussowitsch         PetscCall(PCSetOperators(bddcipc_ctx->bddc, M, M));
25429566063dSJacob Faibussowitsch         PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_pCSR", (PetscObject *)&c));
25439566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)M, MATIS, &ismatis));
2544ff11fd76SStefano Zampini         if (c && ismatis) {
2545ff11fd76SStefano Zampini           Mat       lM;
2546ff11fd76SStefano Zampini           PetscInt *csr, n;
2547ff11fd76SStefano Zampini 
25489566063dSJacob Faibussowitsch           PetscCall(MatISGetLocalMat(M, &lM));
25499566063dSJacob Faibussowitsch           PetscCall(MatGetSize(lM, &n, NULL));
25509566063dSJacob Faibussowitsch           PetscCall(PetscContainerGetPointer(c, (void **)&csr));
25519566063dSJacob Faibussowitsch           PetscCall(PCBDDCSetLocalAdjacencyGraph(bddcipc_ctx->bddc, n, csr, csr + (n + 1), PETSC_COPY_VALUES));
25529566063dSJacob Faibussowitsch           PetscCall(MatISRestoreLocalMat(M, &lM));
2553ff11fd76SStefano Zampini         }
25549566063dSJacob Faibussowitsch         PetscCall(PCSetOptionsPrefix(bddcipc_ctx->bddc, ((PetscObject)ksps[1])->prefix));
25559566063dSJacob Faibussowitsch         PetscCall(PCSetErrorIfFailure(bddcipc_ctx->bddc, pc->erroriffailure));
25569566063dSJacob Faibussowitsch         PetscCall(PCSetFromOptions(bddcipc_ctx->bddc));
25575a1e936bSStefano Zampini 
25585a1e936bSStefano Zampini         /* wrap the interface application */
25599566063dSJacob Faibussowitsch         PetscCall(PCSetType(ppc, PCSHELL));
25609566063dSJacob Faibussowitsch         PetscCall(PCShellSetName(ppc, "FETI-DP pressure"));
25619566063dSJacob Faibussowitsch         PetscCall(PCShellSetContext(ppc, bddcipc_ctx));
25629566063dSJacob Faibussowitsch         PetscCall(PCShellSetSetUp(ppc, PCSetUp_BDDCIPC));
25639566063dSJacob Faibussowitsch         PetscCall(PCShellSetApply(ppc, PCApply_BDDCIPC));
25649566063dSJacob Faibussowitsch         PetscCall(PCShellSetApplyTranspose(ppc, PCApplyTranspose_BDDCIPC));
25659566063dSJacob Faibussowitsch         PetscCall(PCShellSetView(ppc, PCView_BDDCIPC));
25669566063dSJacob Faibussowitsch         PetscCall(PCShellSetDestroy(ppc, PCDestroy_BDDCIPC));
25675a1e936bSStefano Zampini       }
25685a1e936bSStefano Zampini 
25695a1e936bSStefano Zampini       /* determine if we need to assemble M to construct a preconditioner */
25705a1e936bSStefano Zampini       if (!matisok) {
25719566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)M, MATIS, &ismatis));
25729566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompareAny((PetscObject)ppc, &matisok, PCBDDC, PCJACOBI, PCNONE, PCMG, ""));
257348a46eb9SPierre Jolivet         if (ismatis && !matisok) PetscCall(MatConvert(M, MATAIJ, MAT_INPLACE_MATRIX, &M));
25745a1e936bSStefano Zampini       }
2575064a4176SStefano Zampini 
2576064a4176SStefano Zampini       /* run the subproblems to check convergence */
25779566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)newmat)->prefix, "-check_saddlepoint", &check, NULL));
2578064a4176SStefano Zampini       if (check) {
2579064a4176SStefano Zampini         PetscInt i;
2580064a4176SStefano Zampini 
2581064a4176SStefano Zampini         for (i = 0; i < nn; i++) {
2582064a4176SStefano Zampini           KSP       kspC;
2583064a4176SStefano Zampini           PC        pc;
2584064a4176SStefano Zampini           Mat       F, pF;
2585064a4176SStefano Zampini           Vec       x, y;
2586064a4176SStefano Zampini           PetscBool isschur, prec = PETSC_TRUE;
2587064a4176SStefano Zampini 
25889566063dSJacob Faibussowitsch           PetscCall(KSPCreate(PetscObjectComm((PetscObject)ksps[i]), &kspC));
25899566063dSJacob Faibussowitsch           PetscCall(KSPSetOptionsPrefix(kspC, ((PetscObject)ksps[i])->prefix));
25909566063dSJacob Faibussowitsch           PetscCall(KSPAppendOptionsPrefix(kspC, "check_"));
25919566063dSJacob Faibussowitsch           PetscCall(KSPGetOperators(ksps[i], &F, &pF));
25929566063dSJacob Faibussowitsch           PetscCall(PetscObjectTypeCompare((PetscObject)F, MATSCHURCOMPLEMENT, &isschur));
2593064a4176SStefano Zampini           if (isschur) {
2594064a4176SStefano Zampini             KSP  kspS, kspS2;
2595064a4176SStefano Zampini             Mat  A00, pA00, A10, A01, A11;
2596064a4176SStefano Zampini             char prefix[256];
2597064a4176SStefano Zampini 
25989566063dSJacob Faibussowitsch             PetscCall(MatSchurComplementGetKSP(F, &kspS));
25999566063dSJacob Faibussowitsch             PetscCall(MatSchurComplementGetSubMatrices(F, &A00, &pA00, &A01, &A10, &A11));
26009566063dSJacob Faibussowitsch             PetscCall(MatCreateSchurComplement(A00, pA00, A01, A10, A11, &F));
26019566063dSJacob Faibussowitsch             PetscCall(MatSchurComplementGetKSP(F, &kspS2));
26029566063dSJacob Faibussowitsch             PetscCall(PetscSNPrintf(prefix, sizeof(prefix), "%sschur_", ((PetscObject)kspC)->prefix));
26039566063dSJacob Faibussowitsch             PetscCall(KSPSetOptionsPrefix(kspS2, prefix));
26049566063dSJacob Faibussowitsch             PetscCall(KSPGetPC(kspS2, &pc));
26059566063dSJacob Faibussowitsch             PetscCall(PCSetType(pc, PCKSP));
26069566063dSJacob Faibussowitsch             PetscCall(PCKSPSetKSP(pc, kspS));
26079566063dSJacob Faibussowitsch             PetscCall(KSPSetFromOptions(kspS2));
26089566063dSJacob Faibussowitsch             PetscCall(KSPGetPC(kspS2, &pc));
26099566063dSJacob Faibussowitsch             PetscCall(PCSetUseAmat(pc, PETSC_TRUE));
2610064a4176SStefano Zampini           } else {
26119566063dSJacob Faibussowitsch             PetscCall(PetscObjectReference((PetscObject)F));
2612064a4176SStefano Zampini           }
26139566063dSJacob Faibussowitsch           PetscCall(KSPSetFromOptions(kspC));
26149566063dSJacob Faibussowitsch           PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)kspC)->prefix, "-preconditioned", &prec, NULL));
2615064a4176SStefano Zampini           if (prec) {
26169566063dSJacob Faibussowitsch             PetscCall(KSPGetPC(ksps[i], &pc));
26179566063dSJacob Faibussowitsch             PetscCall(KSPSetPC(kspC, pc));
2618064a4176SStefano Zampini           }
26199566063dSJacob Faibussowitsch           PetscCall(KSPSetOperators(kspC, F, pF));
26209566063dSJacob Faibussowitsch           PetscCall(MatCreateVecs(F, &x, &y));
26219566063dSJacob Faibussowitsch           PetscCall(VecSetRandom(x, NULL));
26229566063dSJacob Faibussowitsch           PetscCall(MatMult(F, x, y));
26239566063dSJacob Faibussowitsch           PetscCall(KSPSolve(kspC, y, x));
26249566063dSJacob Faibussowitsch           PetscCall(KSPCheckSolve(kspC, pc, x));
26259566063dSJacob Faibussowitsch           PetscCall(KSPDestroy(&kspC));
26269566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&F));
26279566063dSJacob Faibussowitsch           PetscCall(VecDestroy(&x));
26289566063dSJacob Faibussowitsch           PetscCall(VecDestroy(&y));
2629064a4176SStefano Zampini         }
2630064a4176SStefano Zampini       }
26319566063dSJacob Faibussowitsch       PetscCall(PetscFree(ksps));
2632e1214c54Sstefano_zampini     }
26335a1e936bSStefano Zampini   }
26343425bc38SStefano Zampini   /* return pointers for objects created */
26353425bc38SStefano Zampini   *fetidp_mat = newmat;
26363425bc38SStefano Zampini   *fetidp_pc  = newpc;
26373425bc38SStefano Zampini   PetscFunctionReturn(0);
26383425bc38SStefano Zampini }
26391e6b0712SBarry Smith 
264094ef8ddeSSatish Balay /*@C
26410f202f7eSStefano Zampini  PCBDDCCreateFETIDPOperators - Create FETI-DP operators
26423425bc38SStefano Zampini 
26433425bc38SStefano Zampini    Collective
26443425bc38SStefano Zampini 
26453425bc38SStefano Zampini    Input Parameters:
26461720468bSStefano Zampini +  pc - the BDDC preconditioning context (setup should have been called before)
2647547c9a8eSstefano_zampini .  fully_redundant - true for a fully redundant set of Lagrange multipliers
2648547c9a8eSstefano_zampini -  prefix - optional options database prefix for the objects to be created (can be NULL)
264928509bceSStefano Zampini 
265028509bceSStefano Zampini    Output Parameters:
26510f202f7eSStefano Zampini +  fetidp_mat - shell FETI-DP matrix object
26520f202f7eSStefano Zampini -  fetidp_pc  - shell Dirichlet preconditioner for FETI-DP matrix
265328509bceSStefano Zampini 
26543425bc38SStefano Zampini    Level: developer
26553425bc38SStefano Zampini 
2656*f1580f4eSBarry Smith    Note:
2657*f1580f4eSBarry Smith    Currently the only operations provided for FETI-DP matrix are `MatMult()` and `MatMultTranspose()`
26583425bc38SStefano Zampini 
265916b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCMatFETIDPGetRHS()`, `PCBDDCMatFETIDPGetSolution()`
26603425bc38SStefano Zampini @*/
26619371c9d4SSatish Balay PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc) {
26623425bc38SStefano Zampini   PetscFunctionBegin;
26633425bc38SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
26643425bc38SStefano Zampini   if (pc->setupcalled) {
2665cac4c232SBarry Smith     PetscUseMethod(pc, "PCBDDCCreateFETIDPOperators_C", (PC, PetscBool, const char *, Mat *, PC *), (pc, fully_redundant, prefix, fetidp_mat, fetidp_pc));
26666080607fSStefano Zampini   } else SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "You must call PCSetup_BDDC() first");
26673425bc38SStefano Zampini   PetscFunctionReturn(0);
26683425bc38SStefano Zampini }
2669*f1580f4eSBarry Smith 
2670da1bb401SStefano Zampini /*MC
2671*f1580f4eSBarry Smith    PCBDDC - Balancing Domain Decomposition by Constraints preconditioners
26720c7d97c5SJed Brown 
2673*f1580f4eSBarry Smith    Requires `MATIS` matrices (Pmat) with local matrices (inside the `MATIS`) of type `MATSEQAIJ`, `MATSEQBAIJ` or `MATSEQSBAIJ`
267428509bceSStefano Zampini 
267528509bceSStefano Zampini    It also works with unsymmetric and indefinite problems.
267628509bceSStefano Zampini 
2677*f1580f4eSBarry Smith    Unlike 'conventional' interface preconditioners, `PCBDDC` iterates over all degrees of freedom, not just those on the interface. This allows the use
2678*f1580f4eSBarry Smith    of approximate solvers on the subdomains.
2679b6fdb6dfSStefano Zampini 
2680*f1580f4eSBarry Smith    Approximate local solvers are automatically adapted (see [1]) if the user has attached a nullspace object to the subdomain matrices, and informed
2681*f1580f4eSBarry Smith    `PCBDDC` of using approximate solvers (via the command line).
268228509bceSStefano Zampini 
2683*f1580f4eSBarry Smith    Boundary nodes are split in vertices, edges and faces classes using information from the local to global mapping of dofs and the local connectivity graph of nodes.
2684*f1580f4eSBarry Smith    The latter can be customized by using `PCBDDCSetLocalAdjacencyGraph()`
268528509bceSStefano Zampini 
2686*f1580f4eSBarry Smith    Additional information on dofs can be provided by using `PCBDDCSetDofsSplitting()`, `PCBDDCSetDirichletBoundaries()`, `PCBDDCSetNeumannBoundaries()`, and
2687*f1580f4eSBarry Smith    `PCBDDCSetPrimalVerticesIS()` and their local counterparts.
268828509bceSStefano Zampini 
2689*f1580f4eSBarry Smith    Constraints can be customized by attaching a `MatNullSpace` object to the `MATIS` matrix via `MatSetNearNullSpace()`. Non-singular modes are retained via SVD.
269028509bceSStefano Zampini 
2691*f1580f4eSBarry Smith    Change of basis is performed similarly to [2] when requested. When more than one constraint is present on a single connected component
2692*f1580f4eSBarry Smith    (i.e. an edge or a face), a robust method based on local QR factorizations is used.
2693*f1580f4eSBarry Smith    User defined change of basis can be passed to `PCBDDC` with `PCBDDCSetChangeOfBasisMat()`
269428509bceSStefano Zampini 
2695*f1580f4eSBarry Smith    The PETSc implementation also supports multilevel `PCBDDC` [3]. Coarse grids are partitioned using a `MatPartitioning` object.
269628509bceSStefano Zampini 
2697*f1580f4eSBarry Smith    Adaptive selection of primal constraints [4] is supported for SPD systems with high-contrast in the coefficients if MUMPS or MKL_PARDISO are present.
2698*f1580f4eSBarry Smith    Future versions of the code will also consider using PASTIX.
26990f202f7eSStefano Zampini 
2700*f1580f4eSBarry Smith    An experimental interface to the FETI-DP method is available. FETI-DP operators could be created using `PCBDDCCreateFETIDPOperators()`.
2701*f1580f4eSBarry Smith     A stand-alone class for the FETI-DP method will be provided in the next releases.
27020f202f7eSStefano Zampini 
2703*f1580f4eSBarry Smith    Options Database Keys:
2704a2b725a8SWilliam Gropp +    -pc_bddc_use_vertices <true> - use or not vertices in primal space
27050f202f7eSStefano Zampini .    -pc_bddc_use_edges <true> - use or not edges in primal space
27060f202f7eSStefano Zampini .    -pc_bddc_use_faces <false> - use or not faces in primal space
27070f202f7eSStefano Zampini .    -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems
27080f202f7eSStefano Zampini .    -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only)
27090f202f7eSStefano Zampini .    -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested
27100f202f7eSStefano Zampini .    -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1])
271128509bceSStefano Zampini .    -pc_bddc_levels <0> - maximum number of levels for multilevel
27120f202f7eSStefano 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)
27135459c157SBarry 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)
27140f202f7eSStefano Zampini .    -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling
271571f2caa7Sprj- .    -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)
2716bd2a564bSStefano 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)
271728509bceSStefano Zampini -    -pc_bddc_check_level <0> - set verbosity level of debugging output
271828509bceSStefano Zampini 
2719*f1580f4eSBarry Smith    Options for Dirichlet, Neumann or coarse solver can be set using the appropriate options prefix
272028509bceSStefano Zampini .vb
272128509bceSStefano Zampini       -pc_bddc_dirichlet_
272228509bceSStefano Zampini       -pc_bddc_neumann_
272328509bceSStefano Zampini       -pc_bddc_coarse_
272428509bceSStefano Zampini .ve
2725*f1580f4eSBarry Smith    e.g. -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. `PCBDDC` uses by default `KSPPREONLY` and `PCLU`.
272628509bceSStefano Zampini 
2727*f1580f4eSBarry Smith    When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified using the options prefix
272828509bceSStefano Zampini .vb
2729312be037SStefano Zampini       -pc_bddc_dirichlet_lN_
2730312be037SStefano Zampini       -pc_bddc_neumann_lN_
2731312be037SStefano Zampini       -pc_bddc_coarse_lN_
273228509bceSStefano Zampini .ve
27330f202f7eSStefano Zampini    Note that level number ranges from the finest (0) to the coarsest (N).
2734*f1580f4eSBarry Smith    In order to specify options for the `PCBDDC` operators at the coarser levels (and not for the solvers), prepend -pc_bddc_coarse_ or -pc_bddc_coarse_l
2735*f1580f4eSBarry Smith    to the option, e.g.
27360f202f7eSStefano Zampini .vb
27370f202f7eSStefano Zampini      -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3
27380f202f7eSStefano Zampini .ve
27390f202f7eSStefano 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
2740da1bb401SStefano Zampini 
2741be4a8d98Sprj-    References:
2742606c0280SSatish Balay +  * - C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149--168, March 2007
2743606c0280SSatish 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
2744606c0280SSatish Balay .  * - J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", Computing Volume 83, Issue 2--3, pages 55--85, November 2008
2745606c0280SSatish 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
2746be4a8d98Sprj- 
2747da1bb401SStefano Zampini    Level: intermediate
2748da1bb401SStefano Zampini 
2749da1bb401SStefano Zampini    Contributed by Stefano Zampini
2750da1bb401SStefano Zampini 
2751*f1580f4eSBarry Smith  .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `MATIS`, `PCLU`, `PGGAMG`, `PC`, `PCBDDCSetLocalAdjacencyGraph()`, `PCBDDCSetDofsSplitting()`,
2752*f1580f4eSBarry Smith             `PCBDDCSetDirichletBoundaries()`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCSetPrimalVerticesIS()`, `MatNullSpace`, `MatSetNearNullSpace()`,
2753*f1580f4eSBarry Smith             `PCBDDCSetChangeOfBasisMat()`, `PCBDDCCreateFETIDPOperators()`, `PCNN`
2754da1bb401SStefano Zampini M*/
2755b2573a8aSBarry Smith 
27569371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc) {
2757da1bb401SStefano Zampini   PC_BDDC *pcbddc;
2758da1bb401SStefano Zampini 
2759da1bb401SStefano Zampini   PetscFunctionBegin;
27609566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(pc, &pcbddc));
27613ec1f749SStefano Zampini   pc->data = pcbddc;
2762da1bb401SStefano Zampini 
2763da1bb401SStefano Zampini   /* create PCIS data structure */
27649566063dSJacob Faibussowitsch   PetscCall(PCISCreate(pc));
2765da1bb401SStefano Zampini 
27669326c5c6Sstefano_zampini   /* create local graph structure */
27679566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphCreate(&pcbddc->mat_graph));
27689326c5c6Sstefano_zampini 
27699326c5c6Sstefano_zampini   /* BDDC nonzero defaults */
27706d9e27e4SStefano Zampini   pcbddc->use_nnsp                  = PETSC_TRUE;
277108a5cf49SStefano Zampini   pcbddc->use_local_adj             = PETSC_TRUE;
277247d04d0dSStefano Zampini   pcbddc->use_vertices              = PETSC_TRUE;
277347d04d0dSStefano Zampini   pcbddc->use_edges                 = PETSC_TRUE;
27743301b35fSStefano Zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
277514f95afaSStefano Zampini   pcbddc->vertex_size               = 1;
2776c703fcc7SStefano Zampini   pcbddc->recompute_topography      = PETSC_TRUE;
277768457ee5SStefano Zampini   pcbddc->coarse_size               = -1;
277885c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
277947d04d0dSStefano Zampini   pcbddc->coarsening_ratio          = 8;
278057de7509SStefano Zampini   pcbddc->coarse_eqs_per_proc       = 1;
278127b6a85dSStefano Zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
27821e0482f5SStefano Zampini   pcbddc->nedfield                  = -1;
27831e0482f5SStefano Zampini   pcbddc->nedglobal                 = PETSC_TRUE;
2784be12c134Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
2785b96c3477SStefano Zampini   pcbddc->sub_schurs_layers         = -1;
2786bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[0]     = 0.0;
2787bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[1]     = 0.0;
2788b7eb3628SStefano Zampini 
2789da1bb401SStefano Zampini   /* function pointers */
2790da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
279193bd9ae7SStefano Zampini   pc->ops->applytranspose      = PCApplyTranspose_BDDC;
2792da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
2793da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
2794da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
27956b78500eSPatrick Sanan   pc->ops->view                = PCView_BDDC;
27960a545947SLisandro Dalcin   pc->ops->applyrichardson     = NULL;
27970a545947SLisandro Dalcin   pc->ops->applysymmetricleft  = NULL;
27980a545947SLisandro Dalcin   pc->ops->applysymmetricright = NULL;
2799534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
2800534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
28019326c5c6Sstefano_zampini   pc->ops->reset               = PCReset_BDDC;
2802da1bb401SStefano Zampini 
2803da1bb401SStefano Zampini   /* composing function */
28049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDiscreteGradient_C", PCBDDCSetDiscreteGradient_BDDC));
28059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDivergenceMat_C", PCBDDCSetDivergenceMat_BDDC));
28069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetChangeOfBasisMat_C", PCBDDCSetChangeOfBasisMat_BDDC));
28079566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesLocalIS_C", PCBDDCSetPrimalVerticesLocalIS_BDDC));
28089566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesIS_C", PCBDDCSetPrimalVerticesIS_BDDC));
28099566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesLocalIS_C", PCBDDCGetPrimalVerticesLocalIS_BDDC));
28109566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesIS_C", PCBDDCGetPrimalVerticesIS_BDDC));
28119566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetCoarseningRatio_C", PCBDDCSetCoarseningRatio_BDDC));
28129566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevel_C", PCBDDCSetLevel_BDDC));
28139566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetUseExactDirichlet_C", PCBDDCSetUseExactDirichlet_BDDC));
28149566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevels_C", PCBDDCSetLevels_BDDC));
28159566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundaries_C", PCBDDCSetDirichletBoundaries_BDDC));
28169566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundariesLocal_C", PCBDDCSetDirichletBoundariesLocal_BDDC));
28179566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundaries_C", PCBDDCSetNeumannBoundaries_BDDC));
28189566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundariesLocal_C", PCBDDCSetNeumannBoundariesLocal_BDDC));
28199566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundaries_C", PCBDDCGetDirichletBoundaries_BDDC));
28209566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundariesLocal_C", PCBDDCGetDirichletBoundariesLocal_BDDC));
28219566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundaries_C", PCBDDCGetNeumannBoundaries_BDDC));
28229566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundariesLocal_C", PCBDDCGetNeumannBoundariesLocal_BDDC));
28239566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplitting_C", PCBDDCSetDofsSplitting_BDDC));
28249566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplittingLocal_C", PCBDDCSetDofsSplittingLocal_BDDC));
28259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", PCBDDCSetLocalAdjacencyGraph_BDDC));
28269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCCreateFETIDPOperators_C", PCBDDCCreateFETIDPOperators_BDDC));
28279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetRHS_C", PCBDDCMatFETIDPGetRHS_BDDC));
28289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetSolution_C", PCBDDCMatFETIDPGetSolution_BDDC));
28299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", PCPreSolveChangeRHS_BDDC));
28309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_BDDC));
2831da1bb401SStefano Zampini   PetscFunctionReturn(0);
2832da1bb401SStefano Zampini }
283343371fb9SStefano Zampini 
283443371fb9SStefano Zampini /*@C
2835*f1580f4eSBarry Smith  PCBDDCInitializePackage - This function initializes everything in the `PCBDDC` package. It is called
2836*f1580f4eSBarry Smith     from `PCInitializePackage()`.
283743371fb9SStefano Zampini 
283843371fb9SStefano Zampini  Level: developer
283943371fb9SStefano Zampini 
2840*f1580f4eSBarry Smith  .seealso: `PetscInitialize()`, `PCBDDCFinalizePackage()`
284143371fb9SStefano Zampini @*/
28429371c9d4SSatish Balay PetscErrorCode PCBDDCInitializePackage(void) {
284343371fb9SStefano Zampini   int i;
284443371fb9SStefano Zampini 
284543371fb9SStefano Zampini   PetscFunctionBegin;
284643371fb9SStefano Zampini   if (PCBDDCPackageInitialized) PetscFunctionReturn(0);
284743371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_TRUE;
28489566063dSJacob Faibussowitsch   PetscCall(PetscRegisterFinalize(PCBDDCFinalizePackage));
284943371fb9SStefano Zampini 
285043371fb9SStefano Zampini   /* general events */
28519566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCTopo", PC_CLASSID, &PC_BDDC_Topology[0]));
28529566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCLKSP", PC_CLASSID, &PC_BDDC_LocalSolvers[0]));
28539566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCLWor", PC_CLASSID, &PC_BDDC_LocalWork[0]));
28549566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCorr", PC_CLASSID, &PC_BDDC_CorrectionSetUp[0]));
28559566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCASet", PC_CLASSID, &PC_BDDC_ApproxSetUp[0]));
28569566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCAApp", PC_CLASSID, &PC_BDDC_ApproxApply[0]));
28579566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCSet", PC_CLASSID, &PC_BDDC_CoarseSetUp[0]));
28589566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCKSP", PC_CLASSID, &PC_BDDC_CoarseSolver[0]));
28599566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCAdap", PC_CLASSID, &PC_BDDC_AdaptiveSetUp[0]));
28609566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCScal", PC_CLASSID, &PC_BDDC_Scaling[0]));
28619566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCSchr", PC_CLASSID, &PC_BDDC_Schurs[0]));
28629566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCDirS", PC_CLASSID, &PC_BDDC_Solves[0][0]));
28639566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCNeuS", PC_CLASSID, &PC_BDDC_Solves[0][1]));
28649566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCoaS", PC_CLASSID, &PC_BDDC_Solves[0][2]));
286543371fb9SStefano Zampini   for (i = 1; i < PETSC_PCBDDC_MAXLEVELS; i++) {
286643371fb9SStefano Zampini     char ename[32];
286743371fb9SStefano Zampini 
28689566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCTopo l%02d", i));
28699566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Topology[i]));
28709566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCLKSP l%02d", i));
28719566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_LocalSolvers[i]));
28729566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCLWor l%02d", i));
28739566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_LocalWork[i]));
28749566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCorr l%02d", i));
28759566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CorrectionSetUp[i]));
28769566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCASet l%02d", i));
28779566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_ApproxSetUp[i]));
28789566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCAApp l%02d", i));
28799566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_ApproxApply[i]));
28809566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCSet l%02d", i));
28819566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CoarseSetUp[i]));
28829566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCKSP l%02d", i));
28839566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CoarseSolver[i]));
28849566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCAdap l%02d", i));
28859566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_AdaptiveSetUp[i]));
28869566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCScal l%02d", i));
28879566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Scaling[i]));
28889566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCSchr l%02d", i));
28899566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Schurs[i]));
28909566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCDirS l%02d", i));
28919566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][0]));
28929566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCNeuS l%02d", i));
28939566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][1]));
28949566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCoaS l%02d", i));
28959566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][2]));
289643371fb9SStefano Zampini   }
289743371fb9SStefano Zampini   PetscFunctionReturn(0);
289843371fb9SStefano Zampini }
289943371fb9SStefano Zampini 
290043371fb9SStefano Zampini /*@C
2901*f1580f4eSBarry Smith     PCBDDCFinalizePackage - This function frees everything from the `PCBDDC` package. It is
2902*f1580f4eSBarry Smith     called from `PetscFinalize()` automatically.
290343371fb9SStefano Zampini 
290443371fb9SStefano Zampini     Level: developer
290543371fb9SStefano Zampini 
2906*f1580f4eSBarry Smith  .seealso: `PetscFinalize()`, `PCBDDCInitializePackage()`
290743371fb9SStefano Zampini @*/
29089371c9d4SSatish Balay PetscErrorCode PCBDDCFinalizePackage(void) {
290943371fb9SStefano Zampini   PetscFunctionBegin;
291043371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_FALSE;
291143371fb9SStefano Zampini   PetscFunctionReturn(0);
291243371fb9SStefano Zampini }
2913