xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision a1cb837b240af25cd880af0c0b297e52653cd941)
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 
22dd01b7e5SBarry Smith #include <petsc/private/pcbddcimpl.h> /*I "petscpc.h" I*/ /* header file 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 
5766976f2fSJacob Faibussowitsch static PetscErrorCode PCApply_BDDC(PC, Vec, Vec);
580369aaf7SStefano Zampini 
5966976f2fSJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_BDDC(PC pc, PetscOptionItems *PetscOptionsObject)
60d71ae5a4SJacob Faibussowitsch {
610c7d97c5SJed Brown   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
62e569e4e1SStefano Zampini   PetscInt nt, i;
630c7d97c5SJed Brown 
640c7d97c5SJed Brown   PetscFunctionBegin;
65d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "BDDC options");
668eeda7d8SStefano Zampini   /* Verbose debugging */
679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_check_level", "Verbose output for PCBDDC (intended for debug)", "none", pcbddc->dbg_flag, &pcbddc->dbg_flag, NULL));
68a13144ffSStefano Zampini   /* Approximate solvers */
699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-pc_bddc_interface_ext_type", "Use DIRICHLET or LUMP to extend interface corrections to interior", "PCBDDCSetInterfaceExtType", PCBDDCInterfaceExtTypes, (PetscEnum)pcbddc->interface_extension, (PetscEnum *)&pcbddc->interface_extension, NULL));
70bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET) {
719566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-pc_bddc_dirichlet_approximate", "Inform PCBDDC that we are using approximate Dirichlet solvers", "none", pcbddc->NullSpace_corr[0], &pcbddc->NullSpace_corr[0], NULL));
729566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-pc_bddc_dirichlet_approximate_scale", "Inform PCBDDC that we need to scale the Dirichlet solve", "none", pcbddc->NullSpace_corr[1], &pcbddc->NullSpace_corr[1], NULL));
73bc960bbfSJed Brown   } else {
74bc960bbfSJed Brown     /* This flag is needed/implied by lumping */
75bc960bbfSJed Brown     pcbddc->switch_static = PETSC_TRUE;
76bc960bbfSJed Brown   }
779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_neumann_approximate", "Inform PCBDDC that we are using approximate Neumann solvers", "none", pcbddc->NullSpace_corr[2], &pcbddc->NullSpace_corr[2], NULL));
789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_neumann_approximate_scale", "Inform PCBDDC that we need to scale the Neumann solve", "none", pcbddc->NullSpace_corr[3], &pcbddc->NullSpace_corr[3], NULL));
796b78500eSPatrick Sanan   /* Primal space customization */
809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_local_mat_graph", "Use or not adjacency graph of local mat for interface analysis", "none", pcbddc->use_local_adj, &pcbddc->use_local_adj, NULL));
819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_graph_maxcount", "Maximum number of shared subdomains for a connected component", "none", pcbddc->graphmaxcount, &pcbddc->graphmaxcount, NULL));
829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_corner_selection", "Activates face-based corner selection", "none", pcbddc->corner_selection, &pcbddc->corner_selection, NULL));
839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_vertices", "Use or not corner dofs in coarse space", "none", pcbddc->use_vertices, &pcbddc->use_vertices, NULL));
849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_edges", "Use or not edge constraints in coarse space", "none", pcbddc->use_edges, &pcbddc->use_edges, NULL));
859566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_faces", "Use or not face constraints in coarse space", "none", pcbddc->use_faces, &pcbddc->use_faces, NULL));
869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_vertex_size", "Connected components smaller or equal to vertex size will be considered as primal vertices", "none", pcbddc->vertex_size, &pcbddc->vertex_size, NULL));
879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_nnsp", "Use near null space attached to the matrix to compute constraints", "none", pcbddc->use_nnsp, &pcbddc->use_nnsp, NULL));
889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_nnsp_true", "Use near null space attached to the matrix to compute constraints as is", "none", pcbddc->use_nnsp_true, &pcbddc->use_nnsp_true, NULL));
899566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_qr_single", "Use QR factorization for single constraints on cc (QR is always used when multiple constraints are present)", "none", pcbddc->use_qr_single, &pcbddc->use_qr_single, NULL));
908eeda7d8SStefano Zampini   /* Change of basis */
919566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_change_of_basis", "Use or not internal change of basis on local edge nodes", "none", pcbddc->use_change_of_basis, &pcbddc->use_change_of_basis, NULL));
929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_change_on_faces", "Use or not internal change of basis on local face nodes", "none", pcbddc->use_change_on_faces, &pcbddc->use_change_on_faces, NULL));
93ad540459SPierre Jolivet   if (!pcbddc->use_change_of_basis) pcbddc->use_change_on_faces = PETSC_FALSE;
948eeda7d8SStefano Zampini   /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */
959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_switch_static", "Switch on static condensation ops around the interface preconditioner", "none", pcbddc->switch_static, &pcbddc->switch_static, NULL));
969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_coarse_eqs_per_proc", "Target number of equations per process for coarse problem redistribution (significant only at the coarsest level)", "none", pcbddc->coarse_eqs_per_proc, &pcbddc->coarse_eqs_per_proc, NULL));
97e569e4e1SStefano Zampini   i = pcbddc->coarsening_ratio;
989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_coarsening_ratio", "Set coarsening ratio used in multilevel coarsening", "PCBDDCSetCoarseningRatio", i, &i, NULL));
999566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetCoarseningRatio(pc, i));
100e569e4e1SStefano Zampini   i = pcbddc->max_levels;
1019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_levels", "Set maximum number of levels for multilevel", "PCBDDCSetLevels", i, &i, NULL));
1029566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetLevels(pc, i));
1039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_coarse_eqs_limit", "Set maximum number of equations on coarsest grid to aim for", "none", pcbddc->coarse_eqs_limit, &pcbddc->coarse_eqs_limit, NULL));
1049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_coarse_estimates", "Use estimated eigenvalues for coarse problem", "none", pcbddc->use_coarse_estimates, &pcbddc->use_coarse_estimates, NULL));
1059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_deluxe_scaling", "Use deluxe scaling for BDDC", "none", pcbddc->use_deluxe_scaling, &pcbddc->use_deluxe_scaling, NULL));
1069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_schur_rebuild", "Whether or not the interface graph for Schur principal minors has to be rebuilt (i.e. define the interface without any adjacency)", "none", pcbddc->sub_schurs_rebuild, &pcbddc->sub_schurs_rebuild, NULL));
1079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_schur_layers", "Number of dofs' layers for the computation of principal minors (i.e. -1 uses all dofs)", "none", pcbddc->sub_schurs_layers, &pcbddc->sub_schurs_layers, NULL));
1089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_schur_use_useradj", "Whether or not the CSR graph specified by the user should be used for computing successive layers (default is to use adj of local mat)", "none", pcbddc->sub_schurs_use_useradj, &pcbddc->sub_schurs_use_useradj, NULL));
1099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_schur_exact", "Whether or not to use the exact Schur complement instead of the reduced one (which excludes size 1 cc)", "none", pcbddc->sub_schurs_exact_schur, &pcbddc->sub_schurs_exact_schur, NULL));
1109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_deluxe_zerorows", "Zero rows and columns of deluxe operators associated with primal dofs", "none", pcbddc->deluxe_zerorows, &pcbddc->deluxe_zerorows, NULL));
1119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_deluxe_singlemat", "Collapse deluxe operators", "none", pcbddc->deluxe_singlemat, &pcbddc->deluxe_singlemat, NULL));
1129566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_adaptive_userdefined", "Use user-defined constraints (should be attached via MatSetNearNullSpace to pmat) in addition to those adaptively generated", "none", pcbddc->adaptive_userdefined, &pcbddc->adaptive_userdefined, NULL));
113bd2a564bSStefano Zampini   nt = 2;
1149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRealArray("-pc_bddc_adaptive_threshold", "Thresholds to be used for adaptive selection of constraints", "none", pcbddc->adaptive_threshold, &nt, NULL));
115bd2a564bSStefano Zampini   if (nt == 1) pcbddc->adaptive_threshold[1] = pcbddc->adaptive_threshold[0];
1169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_adaptive_nmin", "Minimum number of constraints per connected components", "none", pcbddc->adaptive_nmin, &pcbddc->adaptive_nmin, NULL));
1179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_adaptive_nmax", "Maximum number of constraints per connected components", "none", pcbddc->adaptive_nmax, &pcbddc->adaptive_nmax, NULL));
1189566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_symmetric", "Symmetric computation of primal basis functions", "none", pcbddc->symmetric_primal, &pcbddc->symmetric_primal, NULL));
1199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_coarse_adj", "Number of processors where to map the coarse adjacency list", "none", pcbddc->coarse_adj_red, &pcbddc->coarse_adj_red, NULL));
1209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_benign_trick", "Apply the benign subspace trick to saddle point problems with discontinuous pressures", "none", pcbddc->benign_saddle_point, &pcbddc->benign_saddle_point, NULL));
1219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_benign_change", "Compute the pressure change of basis explicitly", "none", pcbddc->benign_change_explicit, &pcbddc->benign_change_explicit, NULL));
1229566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_benign_compute_correction", "Compute the benign correction during PreSolve", "none", pcbddc->benign_compute_correction, &pcbddc->benign_compute_correction, NULL));
1239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_nonetflux", "Automatic computation of no-net-flux quadrature weights", "none", pcbddc->compute_nonetflux, &pcbddc->compute_nonetflux, NULL));
1249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_detect_disconnected", "Detects disconnected subdomains", "none", pcbddc->detect_disconnected, &pcbddc->detect_disconnected, NULL));
1259566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_detect_disconnected_filter", "Filters out small entries in the local matrix when detecting disconnected subdomains", "none", pcbddc->detect_disconnected_filter, &pcbddc->detect_disconnected_filter, NULL));
1269566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_eliminate_dirichlet", "Whether or not we want to eliminate dirichlet dofs during presolve", "none", pcbddc->eliminate_dirdofs, &pcbddc->eliminate_dirdofs, NULL));
127d0609cedSBarry Smith   PetscOptionsHeadEnd();
1283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1290c7d97c5SJed Brown }
1306b78500eSPatrick Sanan 
131d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_BDDC(PC pc, PetscViewer viewer)
132d71ae5a4SJacob Faibussowitsch {
1336b78500eSPatrick Sanan   PC_BDDC     *pcbddc = (PC_BDDC *)pc->data;
134e9627c49SStefano Zampini   PC_IS       *pcis   = (PC_IS *)pc->data;
13571783a16SStefano Zampini   PetscBool    isascii;
136e9627c49SStefano Zampini   PetscSubcomm subcomm;
137e9627c49SStefano Zampini   PetscViewer  subviewer;
1386b78500eSPatrick Sanan 
1396b78500eSPatrick Sanan   PetscFunctionBegin;
1409566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1416b78500eSPatrick Sanan   /* ASCII viewer */
1426b78500eSPatrick Sanan   if (isascii) {
1434b2aedd3SStefano Zampini     PetscMPIInt color, rank, size;
144fbad9177SStefano Zampini     PetscInt64  loc[7], gsum[6], gmax[6], gmin[6], totbenign;
145e9627c49SStefano Zampini     PetscScalar interface_size;
146e9627c49SStefano Zampini     PetscReal   ratio1 = 0., ratio2 = 0.;
147e9627c49SStefano Zampini     Vec         counter;
1486b78500eSPatrick Sanan 
14948a46eb9SPierre Jolivet     if (!pc->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, "  Partial information available: preconditioner has not been setup yet\n"));
15063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use verbose output: %" PetscInt_FMT "\n", pcbddc->dbg_flag));
1519566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use user-defined CSR: %d\n", !!pcbddc->mat_graph->nvtxs_csr));
1529566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use local mat graph: %d\n", pcbddc->use_local_adj && !pcbddc->mat_graph->nvtxs_csr));
153e9627c49SStefano Zampini     if (pcbddc->mat_graph->twodim) {
1549566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Connectivity graph topological dimension: 2\n"));
155e9627c49SStefano Zampini     } else {
1569566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Connectivity graph topological dimension: 3\n"));
157e9627c49SStefano Zampini     }
15848a46eb9SPierre Jolivet     if (pcbddc->graphmaxcount != PETSC_MAX_INT) PetscCall(PetscViewerASCIIPrintf(viewer, "  Graph max count: %" PetscInt_FMT "\n", pcbddc->graphmaxcount));
1599566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Corner selection: %d (selected %d)\n", pcbddc->corner_selection, pcbddc->corner_selected));
16063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use vertices: %d (vertex size %" PetscInt_FMT ")\n", pcbddc->use_vertices, pcbddc->vertex_size));
1619566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use edges: %d\n", pcbddc->use_edges));
1629566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use faces: %d\n", pcbddc->use_faces));
1639566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use true near null space: %d\n", pcbddc->use_nnsp_true));
1649566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use QR for single constraints on cc: %d\n", pcbddc->use_qr_single));
1659566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use change of basis on local edge nodes: %d\n", pcbddc->use_change_of_basis));
1669566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use change of basis on local face nodes: %d\n", pcbddc->use_change_on_faces));
1679566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  User defined change of basis matrix: %d\n", !!pcbddc->user_ChangeOfBasisMatrix));
1689566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Has change of basis matrix: %d\n", !!pcbddc->ChangeOfBasisMatrix));
1699566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Eliminate dirichlet boundary dofs: %d\n", pcbddc->eliminate_dirdofs));
1709566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Switch on static condensation ops around the interface preconditioner: %d\n", pcbddc->switch_static));
1719566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use exact dirichlet trick: %d\n", pcbddc->use_exact_dirichlet_trick));
1729566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Interface extension: %s\n", PCBDDCInterfaceExtTypes[pcbddc->interface_extension]));
17363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Multilevel max levels: %" PetscInt_FMT "\n", pcbddc->max_levels));
17463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Multilevel coarsening ratio: %" PetscInt_FMT "\n", pcbddc->coarsening_ratio));
1759566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use estimated eigs for coarse problem: %d\n", pcbddc->use_coarse_estimates));
1769566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use deluxe scaling: %d\n", pcbddc->use_deluxe_scaling));
1779566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use deluxe zerorows: %d\n", pcbddc->deluxe_zerorows));
1789566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use deluxe singlemat: %d\n", pcbddc->deluxe_singlemat));
1799566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Rebuild interface graph for Schur principal minors: %d\n", pcbddc->sub_schurs_rebuild));
18063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of dofs' layers for the computation of principal minors: %" PetscInt_FMT "\n", pcbddc->sub_schurs_layers));
1819566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use user CSR graph to compute successive layers: %d\n", pcbddc->sub_schurs_use_useradj));
182bd2a564bSStefano Zampini     if (pcbddc->adaptive_threshold[1] != pcbddc->adaptive_threshold[0]) {
18363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Adaptive constraint selection thresholds (active %d, userdefined %d): %g,%g\n", pcbddc->adaptive_selection, pcbddc->adaptive_userdefined, (double)pcbddc->adaptive_threshold[0], (double)pcbddc->adaptive_threshold[1]));
184bd2a564bSStefano Zampini     } else {
18563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Adaptive constraint selection threshold (active %d, userdefined %d): %g\n", pcbddc->adaptive_selection, pcbddc->adaptive_userdefined, (double)pcbddc->adaptive_threshold[0]));
186bd2a564bSStefano Zampini     }
18763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Min constraints / connected component: %" PetscInt_FMT "\n", pcbddc->adaptive_nmin));
18863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Max constraints / connected component: %" PetscInt_FMT "\n", pcbddc->adaptive_nmax));
1899566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Invert exact Schur complement for adaptive selection: %d\n", pcbddc->sub_schurs_exact_schur));
1909566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Symmetric computation of primal basis functions: %d\n", pcbddc->symmetric_primal));
19163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Num. Procs. to map coarse adjacency list: %" PetscInt_FMT "\n", pcbddc->coarse_adj_red));
19263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Coarse eqs per proc (significant at the coarsest level): %" PetscInt_FMT "\n", pcbddc->coarse_eqs_per_proc));
1939566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Detect disconnected: %d (filter %d)\n", pcbddc->detect_disconnected, pcbddc->detect_disconnected_filter));
1949566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Benign subspace trick: %d (change explicit %d)\n", pcbddc->benign_saddle_point, pcbddc->benign_change_explicit));
1959566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Benign subspace trick is active: %d\n", pcbddc->benign_have_null));
1969566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Algebraic computation of no-net-flux: %d\n", pcbddc->compute_nonetflux));
1973ba16761SJacob Faibussowitsch     if (!pc->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
1986b78500eSPatrick Sanan 
199fbad9177SStefano Zampini     /* compute interface size */
2009566063dSJacob Faibussowitsch     PetscCall(VecSet(pcis->vec1_B, 1.0));
2019566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(pc->pmat, &counter, NULL));
2029566063dSJacob Faibussowitsch     PetscCall(VecSet(counter, 0.0));
2039566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, counter, INSERT_VALUES, SCATTER_REVERSE));
2049566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, counter, INSERT_VALUES, SCATTER_REVERSE));
2059566063dSJacob Faibussowitsch     PetscCall(VecSum(counter, &interface_size));
2069566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&counter));
207fbad9177SStefano Zampini 
208fbad9177SStefano Zampini     /* compute some statistics on the domain decomposition */
209e9627c49SStefano Zampini     gsum[0] = 1;
210fbad9177SStefano Zampini     gsum[1] = gsum[2] = gsum[3] = gsum[4] = gsum[5] = 0;
211e9627c49SStefano Zampini     loc[0]                                          = !!pcis->n;
212e9627c49SStefano Zampini     loc[1]                                          = pcis->n - pcis->n_B;
213e9627c49SStefano Zampini     loc[2]                                          = pcis->n_B;
214e9627c49SStefano Zampini     loc[3]                                          = pcbddc->local_primal_size;
215345ecf6cSStefano Zampini     loc[4]                                          = pcis->n;
216fbad9177SStefano Zampini     loc[5]                                          = pcbddc->n_local_subs > 0 ? pcbddc->n_local_subs : (pcis->n ? 1 : 0);
217fbad9177SStefano Zampini     loc[6]                                          = pcbddc->benign_n;
2189566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(loc, gsum, 6, MPIU_INT64, MPI_SUM, 0, PetscObjectComm((PetscObject)pc)));
219fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = -1;
2209566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(loc, gmax, 6, MPIU_INT64, MPI_MAX, 0, PetscObjectComm((PetscObject)pc)));
221fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = PETSC_MAX_INT;
2229566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(loc, gmin, 6, MPIU_INT64, MPI_MIN, 0, PetscObjectComm((PetscObject)pc)));
2239566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&loc[6], &totbenign, 1, MPIU_INT64, MPI_SUM, 0, PetscObjectComm((PetscObject)pc)));
224e9627c49SStefano Zampini     if (pcbddc->coarse_size) {
225e9627c49SStefano Zampini       ratio1 = pc->pmat->rmap->N / (1. * pcbddc->coarse_size);
226e9627c49SStefano Zampini       ratio2 = PetscRealPart(interface_size) / pcbddc->coarse_size;
227e9627c49SStefano Zampini     }
22863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "********************************** STATISTICS AT LEVEL %" PetscInt_FMT " **********************************\n", pcbddc->current_level));
22963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Global dofs sizes: all %" PetscInt_FMT " interface %" PetscInt_FMT " coarse %" PetscInt_FMT "\n", pc->pmat->rmap->N, (PetscInt)PetscRealPart(interface_size), pcbddc->coarse_size));
23063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Coarsening ratios: all/coarse %" PetscInt_FMT " interface/coarse %" PetscInt_FMT "\n", (PetscInt)ratio1, (PetscInt)ratio2));
23163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Active processes : %" PetscInt_FMT "\n", (PetscInt)gsum[0]));
23263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Total subdomains : %" PetscInt_FMT "\n", (PetscInt)gsum[5]));
23348a46eb9SPierre Jolivet     if (pcbddc->benign_have_null) PetscCall(PetscViewerASCIIPrintf(viewer, "  Benign subs      : %" PetscInt_FMT "\n", (PetscInt)totbenign));
2349566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Dofs type        :\tMIN\tMAX\tMEAN\n"));
23563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Interior  dofs   :\t%" PetscInt_FMT "\t%" PetscInt_FMT "\t%" PetscInt_FMT "\n", (PetscInt)gmin[1], (PetscInt)gmax[1], (PetscInt)(gsum[1] / gsum[0])));
23663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Interface dofs   :\t%" PetscInt_FMT "\t%" PetscInt_FMT "\t%" PetscInt_FMT "\n", (PetscInt)gmin[2], (PetscInt)gmax[2], (PetscInt)(gsum[2] / gsum[0])));
23763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Primal    dofs   :\t%" PetscInt_FMT "\t%" PetscInt_FMT "\t%" PetscInt_FMT "\n", (PetscInt)gmin[3], (PetscInt)gmax[3], (PetscInt)(gsum[3] / gsum[0])));
23863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Local     dofs   :\t%" PetscInt_FMT "\t%" PetscInt_FMT "\t%" PetscInt_FMT "\n", (PetscInt)gmin[4], (PetscInt)gmax[4], (PetscInt)(gsum[4] / gsum[0])));
23963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Local     subs   :\t%" PetscInt_FMT "\t%" PetscInt_FMT "\n", (PetscInt)gmin[5], (PetscInt)gmax[5]));
2409566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
24115579a77SStefano Zampini 
2429566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc), &rank));
24315579a77SStefano Zampini 
24415579a77SStefano Zampini     /* local solvers */
2459566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetSubViewer(viewer, PetscObjectComm((PetscObject)pcbddc->ksp_D), &subviewer));
246dd400576SPatrick Sanan     if (rank == 0) {
2479566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(subviewer, "--- Interior solver (rank 0)\n"));
2489566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(subviewer));
2499566063dSJacob Faibussowitsch       PetscCall(KSPView(pcbddc->ksp_D, subviewer));
2509566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(subviewer));
2519566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(subviewer, "--- Correction solver (rank 0)\n"));
2529566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(subviewer));
2539566063dSJacob Faibussowitsch       PetscCall(KSPView(pcbddc->ksp_R, subviewer));
2549566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(subviewer));
2559566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(subviewer));
25615579a77SStefano Zampini     }
2579566063dSJacob Faibussowitsch     PetscCall(PetscViewerRestoreSubViewer(viewer, PetscObjectComm((PetscObject)pcbddc->ksp_D), &subviewer));
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   }
2773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2786b78500eSPatrick Sanan }
279a13144ffSStefano Zampini 
280d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDiscreteGradient_BDDC(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
281d71ae5a4SJacob Faibussowitsch {
282a13144ffSStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
283a13144ffSStefano Zampini 
284a13144ffSStefano Zampini   PetscFunctionBegin;
2859566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)G));
2869566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->discretegradient));
287a13144ffSStefano Zampini   pcbddc->discretegradient = G;
288a13144ffSStefano Zampini   pcbddc->nedorder         = order > 0 ? order : -order;
289495a2a07SStefano Zampini   pcbddc->nedfield         = field;
2901e0482f5SStefano Zampini   pcbddc->nedglobal        = global;
2911e0482f5SStefano Zampini   pcbddc->conforming       = conforming;
2923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
293a13144ffSStefano Zampini }
294a13144ffSStefano Zampini 
295a13144ffSStefano Zampini /*@
29698ad52f2SBarry Smith   PCBDDCSetDiscreteGradient - Sets the discrete gradient to be used by the `PCBDDC` preconditioner
297a13144ffSStefano Zampini 
298c3339decSBarry Smith   Collective
299a13144ffSStefano Zampini 
300a13144ffSStefano Zampini   Input Parameters:
301a13144ffSStefano Zampini + pc         - the preconditioning context
302f1580f4eSBarry Smith . G          - the discrete gradient matrix (in `MATAIJ` format)
303a13144ffSStefano Zampini . order      - the order of the Nedelec space (1 for the lowest order)
304495a2a07SStefano Zampini . field      - the field id of the Nedelec dofs (not used if the fields have not been specified)
30598ad52f2SBarry Smith . global     - the type of global ordering for the rows of `G`
306a13144ffSStefano Zampini - conforming - whether the mesh is conforming or not
307a13144ffSStefano Zampini 
308a13144ffSStefano Zampini   Level: advanced
309a13144ffSStefano Zampini 
310f1580f4eSBarry Smith   Note:
31120f4b53cSBarry Smith   The discrete gradient matrix `G` is used to analyze the subdomain edges, and it should not contain any zero entry.
312495a2a07SStefano Zampini   For variable order spaces, the order should be set to zero.
31398ad52f2SBarry Smith   If `global` is `PETSC_TRUE`, the rows of `G` should be given in global ordering for the whole dofs;
31498ad52f2SBarry Smith   if `PETSC_FALSE`, the ordering should be global for the Nedelec field.
3151e0482f5SStefano 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
3161e0482f5SStefano Zampini   and geid the one for the Nedelec field.
317a13144ffSStefano Zampini 
318562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDofsSplitting()`, `PCBDDCSetDofsSplittingLocal()`, `MATAIJ`, `PCBDDCSetDivergenceMat()`
319a13144ffSStefano Zampini @*/
320d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDiscreteGradient(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
321d71ae5a4SJacob Faibussowitsch {
322a13144ffSStefano Zampini   PetscFunctionBegin;
323a13144ffSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
324a13144ffSStefano Zampini   PetscValidHeaderSpecific(G, MAT_CLASSID, 2);
325a13144ffSStefano Zampini   PetscValidLogicalCollectiveInt(pc, order, 3);
3261e0482f5SStefano Zampini   PetscValidLogicalCollectiveInt(pc, field, 4);
3271e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc, global, 5);
3281e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc, conforming, 6);
3291e0482f5SStefano Zampini   PetscCheckSameComm(pc, 1, G, 2);
330cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDiscreteGradient_C", (PC, Mat, PetscInt, PetscInt, PetscBool, PetscBool), (pc, G, order, field, global, conforming));
3313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
332a13144ffSStefano Zampini }
333a13144ffSStefano Zampini 
334d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDivergenceMat_BDDC(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
335d71ae5a4SJacob Faibussowitsch {
336a198735bSStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
3376b78500eSPatrick Sanan 
338a198735bSStefano Zampini   PetscFunctionBegin;
3399566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)divudotp));
3409566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->divudotp));
341a198735bSStefano Zampini   pcbddc->divudotp          = divudotp;
3428ae0ca82SStefano Zampini   pcbddc->divudotp_trans    = trans;
343a198735bSStefano Zampini   pcbddc->compute_nonetflux = PETSC_TRUE;
344a198735bSStefano Zampini   if (vl2l) {
3459566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)vl2l));
3469566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&pcbddc->divudotp_vl2l));
347a198735bSStefano Zampini     pcbddc->divudotp_vl2l = vl2l;
348a198735bSStefano Zampini   }
3493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
350a198735bSStefano Zampini }
3513d996552SStefano Zampini 
352a198735bSStefano Zampini /*@
35398ad52f2SBarry Smith   PCBDDCSetDivergenceMat - Sets the linear operator representing \int_\Omega \div {\bf u} \cdot p dx for the `PCBDDC` preconditioner
354a198735bSStefano Zampini 
355c3339decSBarry Smith   Collective
356a198735bSStefano Zampini 
357a198735bSStefano Zampini   Input Parameters:
358a198735bSStefano Zampini + pc       - the preconditioning context
359f1580f4eSBarry Smith . divudotp - the matrix (must be of type `MATIS`)
36098ad52f2SBarry Smith . trans    - if `PETSC_FALSE` (resp. `PETSC_TRUE`), then pressures are in the test (trial) space and velocities are in the trial (test) space.
36198ad52f2SBarry Smith - vl2l     - optional index set describing the local (wrt the local matrix in `divudotp`) to local (wrt the local matrix
362f1580f4eSBarry Smith    in the preconditioning matrix) map for the velocities
363a198735bSStefano Zampini 
364a198735bSStefano Zampini   Level: advanced
365a198735bSStefano Zampini 
36695452b02SPatrick Sanan   Notes:
36795452b02SPatrick Sanan   This auxiliary matrix is used to compute quadrature weights representing the net-flux across subdomain boundaries
368f1580f4eSBarry Smith 
36998ad52f2SBarry Smith   If `vl2l` is `NULL`, the local ordering for velocities in `divudotp` should match that of the preconditioning matrix
370a198735bSStefano Zampini 
371562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDiscreteGradient()`
372a198735bSStefano Zampini @*/
373d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDivergenceMat(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
374d71ae5a4SJacob Faibussowitsch {
375a198735bSStefano Zampini   PetscBool ismatis;
376a198735bSStefano Zampini 
377a198735bSStefano Zampini   PetscFunctionBegin;
378a198735bSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
379a198735bSStefano Zampini   PetscValidHeaderSpecific(divudotp, MAT_CLASSID, 2);
380a198735bSStefano Zampini   PetscCheckSameComm(pc, 1, divudotp, 2);
3818ae0ca82SStefano Zampini   PetscValidLogicalCollectiveBool(pc, trans, 3);
3821b24a7afSStefano Zampini   if (vl2l) PetscValidHeaderSpecific(vl2l, IS_CLASSID, 4);
3839566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)divudotp, MATIS, &ismatis));
38428b400f6SJacob Faibussowitsch   PetscCheck(ismatis, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Divergence matrix needs to be of type MATIS");
385cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDivergenceMat_C", (PC, Mat, PetscBool, IS), (pc, divudotp, trans, vl2l));
3863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
387a198735bSStefano Zampini }
3882d505d7fSStefano Zampini 
389d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change, PetscBool interior)
390d71ae5a4SJacob Faibussowitsch {
391b9b85e73SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
392b9b85e73SStefano Zampini 
393b9b85e73SStefano Zampini   PetscFunctionBegin;
3949566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)change));
3959566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->user_ChangeOfBasisMatrix));
396b9b85e73SStefano Zampini   pcbddc->user_ChangeOfBasisMatrix = change;
3971dd7afcfSStefano Zampini   pcbddc->change_interior          = interior;
3983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
399b9b85e73SStefano Zampini }
40032fe681dSStefano Zampini 
401b9b85e73SStefano Zampini /*@
402906d46d4SStefano Zampini   PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs
403b9b85e73SStefano Zampini 
404c3339decSBarry Smith   Collective
405b9b85e73SStefano Zampini 
406b9b85e73SStefano Zampini   Input Parameters:
407b9b85e73SStefano Zampini + pc       - the preconditioning context
4081dd7afcfSStefano Zampini . change   - the change of basis matrix
4091dd7afcfSStefano Zampini - interior - whether or not the change of basis modifies interior dofs
410b9b85e73SStefano Zampini 
411b9b85e73SStefano Zampini   Level: intermediate
412b9b85e73SStefano Zampini 
413562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`
414b9b85e73SStefano Zampini @*/
415d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change, PetscBool interior)
416d71ae5a4SJacob Faibussowitsch {
417b9b85e73SStefano Zampini   PetscFunctionBegin;
418b9b85e73SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
419b9b85e73SStefano Zampini   PetscValidHeaderSpecific(change, MAT_CLASSID, 2);
420906d46d4SStefano Zampini   PetscCheckSameComm(pc, 1, change, 2);
421906d46d4SStefano Zampini   if (pc->mat) {
422906d46d4SStefano Zampini     PetscInt rows_c, cols_c, rows, cols;
4239566063dSJacob Faibussowitsch     PetscCall(MatGetSize(pc->mat, &rows, &cols));
4249566063dSJacob Faibussowitsch     PetscCall(MatGetSize(change, &rows_c, &cols_c));
42563a3b9bcSJacob 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);
42663a3b9bcSJacob 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);
4279566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(pc->mat, &rows, &cols));
4289566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(change, &rows_c, &cols_c));
42963a3b9bcSJacob 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);
43063a3b9bcSJacob 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);
431906d46d4SStefano Zampini   }
432cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetChangeOfBasisMat_C", (PC, Mat, PetscBool), (pc, change, interior));
4333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
434b9b85e73SStefano Zampini }
4352d505d7fSStefano Zampini 
436d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetPrimalVerticesIS_BDDC(PC pc, IS PrimalVertices)
437d71ae5a4SJacob Faibussowitsch {
43830368db7SStefano Zampini   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
43956282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
44030368db7SStefano Zampini 
44130368db7SStefano Zampini   PetscFunctionBegin;
4429566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)PrimalVertices));
44348a46eb9SPierre Jolivet   if (pcbddc->user_primal_vertices) PetscCall(ISEqual(PrimalVertices, pcbddc->user_primal_vertices, &isequal));
4449566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices));
4459566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local));
44630368db7SStefano Zampini   pcbddc->user_primal_vertices = PrimalVertices;
44756282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
4483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44930368db7SStefano Zampini }
450ab8c8b98SStefano Zampini 
45130368db7SStefano Zampini /*@
452f1580f4eSBarry Smith   PCBDDCSetPrimalVerticesIS - Set additional user defined primal vertices in `PCBDDC`
45330368db7SStefano Zampini 
45430368db7SStefano Zampini   Collective
45530368db7SStefano Zampini 
45630368db7SStefano Zampini   Input Parameters:
45730368db7SStefano Zampini + pc             - the preconditioning context
45830368db7SStefano Zampini - PrimalVertices - index set of primal vertices in global numbering (can be empty)
45930368db7SStefano Zampini 
46030368db7SStefano Zampini   Level: intermediate
46130368db7SStefano Zampini 
462f1580f4eSBarry Smith   Note:
46330368db7SStefano Zampini   Any process can list any global node
46430368db7SStefano Zampini 
465562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`, `PCBDDCGetPrimalVerticesLocalIS()`
46630368db7SStefano Zampini @*/
467d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetPrimalVerticesIS(PC pc, IS PrimalVertices)
468d71ae5a4SJacob Faibussowitsch {
46930368db7SStefano Zampini   PetscFunctionBegin;
47030368db7SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
47130368db7SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices, IS_CLASSID, 2);
47230368db7SStefano Zampini   PetscCheckSameComm(pc, 1, PrimalVertices, 2);
473cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetPrimalVerticesIS_C", (PC, IS), (pc, PrimalVertices));
4743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47530368db7SStefano Zampini }
4762d505d7fSStefano Zampini 
477d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetPrimalVerticesIS_BDDC(PC pc, IS *is)
478d71ae5a4SJacob Faibussowitsch {
4793100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
4803100ebe3SStefano Zampini 
4813100ebe3SStefano Zampini   PetscFunctionBegin;
4823100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices;
4833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4843100ebe3SStefano Zampini }
4853100ebe3SStefano Zampini 
4863100ebe3SStefano Zampini /*@
487f1580f4eSBarry Smith   PCBDDCGetPrimalVerticesIS - Get user defined primal vertices set with `PCBDDCSetPrimalVerticesIS()`
4883100ebe3SStefano Zampini 
4893100ebe3SStefano Zampini   Collective
4903100ebe3SStefano Zampini 
491f1580f4eSBarry Smith   Input Parameter:
4923100ebe3SStefano Zampini . pc - the preconditioning context
4933100ebe3SStefano Zampini 
494f1580f4eSBarry Smith   Output Parameter:
49520f4b53cSBarry Smith . is - index set of primal vertices in global numbering (`NULL` if not set)
4963100ebe3SStefano Zampini 
4973100ebe3SStefano Zampini   Level: intermediate
4983100ebe3SStefano Zampini 
499562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`, `PCBDDCGetPrimalVerticesLocalIS()`
5003100ebe3SStefano Zampini @*/
501d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetPrimalVerticesIS(PC pc, IS *is)
502d71ae5a4SJacob Faibussowitsch {
5033100ebe3SStefano Zampini   PetscFunctionBegin;
5043100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
5054f572ea9SToby Isaac   PetscAssertPointer(is, 2);
506cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetPrimalVerticesIS_C", (PC, IS *), (pc, is));
5073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5083100ebe3SStefano Zampini }
5093100ebe3SStefano Zampini 
510d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
511d71ae5a4SJacob Faibussowitsch {
512674ae819SStefano Zampini   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
51356282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
5141e6b0712SBarry Smith 
515674ae819SStefano Zampini   PetscFunctionBegin;
5169566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)PrimalVertices));
51748a46eb9SPierre Jolivet   if (pcbddc->user_primal_vertices_local) PetscCall(ISEqual(PrimalVertices, pcbddc->user_primal_vertices_local, &isequal));
5189566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices));
5199566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local));
52030368db7SStefano Zampini   pcbddc->user_primal_vertices_local = PrimalVertices;
52156282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
5223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
523674ae819SStefano Zampini }
5243100ebe3SStefano Zampini 
525674ae819SStefano Zampini /*@
526f1580f4eSBarry Smith   PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in `PCBDDC`
527674ae819SStefano Zampini 
52817eb1463SStefano Zampini   Collective
529674ae819SStefano Zampini 
530674ae819SStefano Zampini   Input Parameters:
531674ae819SStefano Zampini + pc             - the preconditioning context
53217eb1463SStefano Zampini - PrimalVertices - index set of primal vertices in local numbering (can be empty)
533674ae819SStefano Zampini 
534674ae819SStefano Zampini   Level: intermediate
535674ae819SStefano Zampini 
536562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesLocalIS()`
537674ae819SStefano Zampini @*/
538d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
539d71ae5a4SJacob Faibussowitsch {
540674ae819SStefano Zampini   PetscFunctionBegin;
541674ae819SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
542674ae819SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices, IS_CLASSID, 2);
54317eb1463SStefano Zampini   PetscCheckSameComm(pc, 1, PrimalVertices, 2);
544cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetPrimalVerticesLocalIS_C", (PC, IS), (pc, PrimalVertices));
5453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
546674ae819SStefano Zampini }
5472d505d7fSStefano Zampini 
548d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetPrimalVerticesLocalIS_BDDC(PC pc, IS *is)
549d71ae5a4SJacob Faibussowitsch {
5503100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
5513100ebe3SStefano Zampini 
5523100ebe3SStefano Zampini   PetscFunctionBegin;
5533100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices_local;
5543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5553100ebe3SStefano Zampini }
5563100ebe3SStefano Zampini 
5573100ebe3SStefano Zampini /*@
558f1580f4eSBarry Smith   PCBDDCGetPrimalVerticesLocalIS - Get user defined primal vertices set with `PCBDDCSetPrimalVerticesLocalIS()`
5593100ebe3SStefano Zampini 
5603100ebe3SStefano Zampini   Collective
5613100ebe3SStefano Zampini 
562f1580f4eSBarry Smith   Input Parameter:
5633100ebe3SStefano Zampini . pc - the preconditioning context
5643100ebe3SStefano Zampini 
565f1580f4eSBarry Smith   Output Parameter:
56620f4b53cSBarry Smith . is - index set of primal vertices in local numbering (`NULL` if not set)
5673100ebe3SStefano Zampini 
5683100ebe3SStefano Zampini   Level: intermediate
5693100ebe3SStefano Zampini 
570562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`
5713100ebe3SStefano Zampini @*/
572d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetPrimalVerticesLocalIS(PC pc, IS *is)
573d71ae5a4SJacob Faibussowitsch {
5743100ebe3SStefano Zampini   PetscFunctionBegin;
5753100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
5764f572ea9SToby Isaac   PetscAssertPointer(is, 2);
577cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetPrimalVerticesLocalIS_C", (PC, IS *), (pc, is));
5783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5793100ebe3SStefano Zampini }
5803100ebe3SStefano Zampini 
581d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc, PetscInt k)
582d71ae5a4SJacob Faibussowitsch {
5834fad6a16SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
5844fad6a16SStefano Zampini 
5854fad6a16SStefano Zampini   PetscFunctionBegin;
5864fad6a16SStefano Zampini   pcbddc->coarsening_ratio = k;
5873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5884fad6a16SStefano Zampini }
5891e6b0712SBarry Smith 
5904fad6a16SStefano Zampini /*@
59198ad52f2SBarry Smith   PCBDDCSetCoarseningRatio - Set coarsening ratio used in the multi-level version of `PCBDDC`
5924fad6a16SStefano Zampini 
59320f4b53cSBarry Smith   Logically Collective
5944fad6a16SStefano Zampini 
5954fad6a16SStefano Zampini   Input Parameters:
5964fad6a16SStefano Zampini + pc - the preconditioning context
59728509bceSStefano Zampini - k  - coarsening ratio (H/h at the coarser level)
5984fad6a16SStefano Zampini 
599f1580f4eSBarry Smith   Options Database Key:
60098ad52f2SBarry Smith . -pc_bddc_coarsening_ratio <int> - Set the coarsening ratio used in multi-level coarsening
6014fad6a16SStefano Zampini 
6024fad6a16SStefano Zampini   Level: intermediate
6034fad6a16SStefano Zampini 
604f1580f4eSBarry Smith   Note:
60520f4b53cSBarry Smith   Approximately `k` subdomains at the finer level will be aggregated into a single subdomain at the coarser level
6064fad6a16SStefano Zampini 
607562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetLevels()`
6084fad6a16SStefano Zampini @*/
609d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetCoarseningRatio(PC pc, PetscInt k)
610d71ae5a4SJacob Faibussowitsch {
6114fad6a16SStefano Zampini   PetscFunctionBegin;
6124fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
6132b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc, k, 2);
614cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetCoarseningRatio_C", (PC, PetscInt), (pc, k));
6153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6164fad6a16SStefano Zampini }
6172b510759SStefano Zampini 
618b8ffe317SStefano Zampini /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */
619d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc, PetscBool flg)
620d71ae5a4SJacob Faibussowitsch {
621b8ffe317SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
622b8ffe317SStefano Zampini 
623b8ffe317SStefano Zampini   PetscFunctionBegin;
62485c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = flg;
6253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
626b8ffe317SStefano Zampini }
627b8ffe317SStefano Zampini 
628d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc, PetscBool flg)
629d71ae5a4SJacob Faibussowitsch {
6302b510759SStefano Zampini   PetscFunctionBegin;
6312b510759SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
632b8ffe317SStefano Zampini   PetscValidLogicalCollectiveBool(pc, flg, 2);
633cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetUseExactDirichlet_C", (PC, PetscBool), (pc, flg));
6343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6352b510759SStefano Zampini }
6361e6b0712SBarry Smith 
637d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc, PetscInt level)
638d71ae5a4SJacob Faibussowitsch {
6394fad6a16SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
6404fad6a16SStefano Zampini 
6414fad6a16SStefano Zampini   PetscFunctionBegin;
6422b510759SStefano Zampini   pcbddc->current_level = level;
6433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6444fad6a16SStefano Zampini }
6451e6b0712SBarry Smith 
646d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetLevel(PC pc, PetscInt level)
647d71ae5a4SJacob Faibussowitsch {
648b8ffe317SStefano Zampini   PetscFunctionBegin;
649b8ffe317SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
650b8ffe317SStefano Zampini   PetscValidLogicalCollectiveInt(pc, level, 2);
651cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetLevel_C", (PC, PetscInt), (pc, level));
6523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
653b8ffe317SStefano Zampini }
654b8ffe317SStefano Zampini 
655d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc, PetscInt levels)
656d71ae5a4SJacob Faibussowitsch {
6572b510759SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
6582b510759SStefano Zampini 
6592b510759SStefano Zampini   PetscFunctionBegin;
6607827d75bSBarry 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);
6612b510759SStefano Zampini   pcbddc->max_levels = levels;
6623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6632b510759SStefano Zampini }
6642b510759SStefano Zampini 
6654fad6a16SStefano Zampini /*@
666f1580f4eSBarry Smith   PCBDDCSetLevels - Sets the maximum number of additional levels allowed for multilevel `PCBDDC`
6674fad6a16SStefano Zampini 
66820f4b53cSBarry Smith   Logically Collective
6694fad6a16SStefano Zampini 
6704fad6a16SStefano Zampini   Input Parameters:
6714fad6a16SStefano Zampini + pc     - the preconditioning context
67237ebbdf7SStefano Zampini - levels - the maximum number of levels
6734fad6a16SStefano Zampini 
674f1580f4eSBarry Smith   Options Database Key:
67567b8a455SSatish Balay . -pc_bddc_levels <int> - Set maximum number of levels for multilevel
6764fad6a16SStefano Zampini 
6774fad6a16SStefano Zampini   Level: intermediate
6784fad6a16SStefano Zampini 
679f1580f4eSBarry Smith   Note:
68098ad52f2SBarry Smith   The default value is 0, that gives the classical two-levels BDDC algorithm
6814fad6a16SStefano Zampini 
682562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetCoarseningRatio()`
6834fad6a16SStefano Zampini @*/
684d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetLevels(PC pc, PetscInt levels)
685d71ae5a4SJacob Faibussowitsch {
6864fad6a16SStefano Zampini   PetscFunctionBegin;
6874fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
6882b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc, levels, 2);
689cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetLevels_C", (PC, PetscInt), (pc, levels));
6903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6914fad6a16SStefano Zampini }
6921e6b0712SBarry Smith 
693d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc, IS DirichletBoundaries)
694d71ae5a4SJacob Faibussowitsch {
6953b03a366Sstefano_zampini   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
69656282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
6973b03a366Sstefano_zampini 
6983b03a366Sstefano_zampini   PetscFunctionBegin;
6999566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)DirichletBoundaries));
70048a46eb9SPierre Jolivet   if (pcbddc->DirichletBoundaries) PetscCall(ISEqual(DirichletBoundaries, pcbddc->DirichletBoundaries, &isequal));
701a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
7029566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal));
7039566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundaries));
70436e030ebSStefano Zampini   pcbddc->DirichletBoundaries = DirichletBoundaries;
70556282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7073b03a366Sstefano_zampini }
7081e6b0712SBarry Smith 
7093b03a366Sstefano_zampini /*@
71098ad52f2SBarry Smith   PCBDDCSetDirichletBoundaries - Set the `IS` defining Dirichlet boundaries for the global problem.
7113b03a366Sstefano_zampini 
712785d1243SStefano Zampini   Collective
7133b03a366Sstefano_zampini 
7143b03a366Sstefano_zampini   Input Parameters:
7153b03a366Sstefano_zampini + pc                  - the preconditioning context
71620f4b53cSBarry Smith - DirichletBoundaries - parallel `IS` defining the Dirichlet boundaries
7173b03a366Sstefano_zampini 
7183b03a366Sstefano_zampini   Level: intermediate
7193b03a366Sstefano_zampini 
720f1580f4eSBarry Smith   Note:
721f1580f4eSBarry Smith   Provide the information if you used `MatZeroRows()` or `MatZeroRowsColumns()`. Any process can list any global node
7223b03a366Sstefano_zampini 
723562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDirichletBoundariesLocal()`, `MatZeroRows()`, `MatZeroRowsColumns()`
7243b03a366Sstefano_zampini @*/
725d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc, IS DirichletBoundaries)
726d71ae5a4SJacob Faibussowitsch {
7273b03a366Sstefano_zampini   PetscFunctionBegin;
7283b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
729674ae819SStefano Zampini   PetscValidHeaderSpecific(DirichletBoundaries, IS_CLASSID, 2);
730785d1243SStefano Zampini   PetscCheckSameComm(pc, 1, DirichletBoundaries, 2);
731cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDirichletBoundaries_C", (PC, IS), (pc, DirichletBoundaries));
7323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7333b03a366Sstefano_zampini }
7341e6b0712SBarry Smith 
735d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc, IS DirichletBoundaries)
736d71ae5a4SJacob Faibussowitsch {
7373b03a366Sstefano_zampini   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
73856282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
7393b03a366Sstefano_zampini 
7403b03a366Sstefano_zampini   PetscFunctionBegin;
7419566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)DirichletBoundaries));
74248a46eb9SPierre Jolivet   if (pcbddc->DirichletBoundariesLocal) PetscCall(ISEqual(DirichletBoundaries, pcbddc->DirichletBoundariesLocal, &isequal));
743a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
7449566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal));
7459566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundaries));
746785d1243SStefano Zampini   pcbddc->DirichletBoundariesLocal = DirichletBoundaries;
74756282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7493b03a366Sstefano_zampini }
7503b03a366Sstefano_zampini 
7513b03a366Sstefano_zampini /*@
75298ad52f2SBarry Smith   PCBDDCSetDirichletBoundariesLocal - Set the `IS` defining Dirichlet boundaries for the global problem in local ordering.
7533b03a366Sstefano_zampini 
754785d1243SStefano Zampini   Collective
7553b03a366Sstefano_zampini 
7563b03a366Sstefano_zampini   Input Parameters:
7573b03a366Sstefano_zampini + pc                  - the preconditioning context
75820f4b53cSBarry Smith - DirichletBoundaries - parallel `IS` defining the Dirichlet boundaries (in local ordering)
7593b03a366Sstefano_zampini 
7603b03a366Sstefano_zampini   Level: intermediate
7613b03a366Sstefano_zampini 
762562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDirichletBoundaries()`, `MatZeroRows()`, `MatZeroRowsColumns()`
7633b03a366Sstefano_zampini @*/
764d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc, IS DirichletBoundaries)
765d71ae5a4SJacob Faibussowitsch {
7663b03a366Sstefano_zampini   PetscFunctionBegin;
7673b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
7683b03a366Sstefano_zampini   PetscValidHeaderSpecific(DirichletBoundaries, IS_CLASSID, 2);
76982ba6b80SStefano Zampini   PetscCheckSameComm(pc, 1, DirichletBoundaries, 2);
770cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDirichletBoundariesLocal_C", (PC, IS), (pc, DirichletBoundaries));
7713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7723b03a366Sstefano_zampini }
7733b03a366Sstefano_zampini 
774d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc, IS NeumannBoundaries)
775d71ae5a4SJacob Faibussowitsch {
7760c7d97c5SJed Brown   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
77756282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
7780c7d97c5SJed Brown 
7790c7d97c5SJed Brown   PetscFunctionBegin;
7809566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries));
78148a46eb9SPierre Jolivet   if (pcbddc->NeumannBoundaries) PetscCall(ISEqual(NeumannBoundaries, pcbddc->NeumannBoundaries, &isequal));
782a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
7839566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal));
7849566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundaries));
78536e030ebSStefano Zampini   pcbddc->NeumannBoundaries = NeumannBoundaries;
78656282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7880c7d97c5SJed Brown }
7891e6b0712SBarry Smith 
79057527edcSJed Brown /*@
79198ad52f2SBarry Smith   PCBDDCSetNeumannBoundaries - Set the `IS` defining Neumann boundaries for the global problem.
79257527edcSJed Brown 
793c3339decSBarry Smith   Collective
79457527edcSJed Brown 
79557527edcSJed Brown   Input Parameters:
79657527edcSJed Brown + pc                - the preconditioning context
79720f4b53cSBarry Smith - NeumannBoundaries - parallel `IS` defining the Neumann boundaries
79857527edcSJed Brown 
79957527edcSJed Brown   Level: intermediate
80057527edcSJed Brown 
801f1580f4eSBarry Smith   Note:
8020f202f7eSStefano Zampini   Any process can list any global node
80357527edcSJed Brown 
804562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetNeumannBoundariesLocal()`
80557527edcSJed Brown @*/
806d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc, IS NeumannBoundaries)
807d71ae5a4SJacob Faibussowitsch {
8080c7d97c5SJed Brown   PetscFunctionBegin;
8090c7d97c5SJed Brown   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
810674ae819SStefano Zampini   PetscValidHeaderSpecific(NeumannBoundaries, IS_CLASSID, 2);
811785d1243SStefano Zampini   PetscCheckSameComm(pc, 1, NeumannBoundaries, 2);
812cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetNeumannBoundaries_C", (PC, IS), (pc, NeumannBoundaries));
8133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81453cdbc3dSStefano Zampini }
8151e6b0712SBarry Smith 
816d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc, IS NeumannBoundaries)
817d71ae5a4SJacob Faibussowitsch {
8180c7d97c5SJed Brown   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
81956282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
8200c7d97c5SJed Brown 
8210c7d97c5SJed Brown   PetscFunctionBegin;
8229566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries));
82348a46eb9SPierre Jolivet   if (pcbddc->NeumannBoundariesLocal) PetscCall(ISEqual(NeumannBoundaries, pcbddc->NeumannBoundariesLocal, &isequal));
824a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
8259566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal));
8269566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundaries));
827785d1243SStefano Zampini   pcbddc->NeumannBoundariesLocal = NeumannBoundaries;
82856282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
8293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8300c7d97c5SJed Brown }
8310c7d97c5SJed Brown 
8320c7d97c5SJed Brown /*@
83398ad52f2SBarry Smith   PCBDDCSetNeumannBoundariesLocal - Set the `IS` defining Neumann boundaries for the global problem in local ordering.
8340c7d97c5SJed Brown 
835785d1243SStefano Zampini   Collective
8360c7d97c5SJed Brown 
8370c7d97c5SJed Brown   Input Parameters:
8380c7d97c5SJed Brown + pc                - the preconditioning context
83920f4b53cSBarry Smith - NeumannBoundaries - parallel `IS` defining the subdomain part of Neumann boundaries (in local ordering)
8400c7d97c5SJed Brown 
8410c7d97c5SJed Brown   Level: intermediate
8420c7d97c5SJed Brown 
843562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCGetDirichletBoundaries()`
8440c7d97c5SJed Brown @*/
845d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc, IS NeumannBoundaries)
846d71ae5a4SJacob Faibussowitsch {
8470c7d97c5SJed Brown   PetscFunctionBegin;
8480c7d97c5SJed Brown   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
8490c7d97c5SJed Brown   PetscValidHeaderSpecific(NeumannBoundaries, IS_CLASSID, 2);
85082ba6b80SStefano Zampini   PetscCheckSameComm(pc, 1, NeumannBoundaries, 2);
851cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetNeumannBoundariesLocal_C", (PC, IS), (pc, NeumannBoundaries));
8523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
85353cdbc3dSStefano Zampini }
85453cdbc3dSStefano Zampini 
855d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc, IS *DirichletBoundaries)
856d71ae5a4SJacob Faibussowitsch {
857da1bb401SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
858da1bb401SStefano Zampini 
859da1bb401SStefano Zampini   PetscFunctionBegin;
860da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
8613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
862da1bb401SStefano Zampini }
8631e6b0712SBarry Smith 
864da1bb401SStefano Zampini /*@
865f1580f4eSBarry Smith   PCBDDCGetDirichletBoundaries - Get parallel `IS` for Dirichlet boundaries
866da1bb401SStefano Zampini 
867785d1243SStefano Zampini   Collective
868785d1243SStefano Zampini 
869f1580f4eSBarry Smith   Input Parameter:
870785d1243SStefano Zampini . pc - the preconditioning context
871785d1243SStefano Zampini 
872f1580f4eSBarry Smith   Output Parameter:
873785d1243SStefano Zampini . DirichletBoundaries - index set defining the Dirichlet boundaries
874785d1243SStefano Zampini 
875785d1243SStefano Zampini   Level: intermediate
876785d1243SStefano Zampini 
877f1580f4eSBarry Smith   Note:
878f1580f4eSBarry Smith   The `IS` returned (if any) is the same passed in earlier by the user with `PCBDDCSetDirichletBoundaries()`
879785d1243SStefano Zampini 
880562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDirichletBoundaries()`
881785d1243SStefano Zampini @*/
882d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc, IS *DirichletBoundaries)
883d71ae5a4SJacob Faibussowitsch {
884785d1243SStefano Zampini   PetscFunctionBegin;
885785d1243SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
886cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetDirichletBoundaries_C", (PC, IS *), (pc, DirichletBoundaries));
8873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
888785d1243SStefano Zampini }
889785d1243SStefano Zampini 
890d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc, IS *DirichletBoundaries)
891d71ae5a4SJacob Faibussowitsch {
892785d1243SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
893785d1243SStefano Zampini 
894785d1243SStefano Zampini   PetscFunctionBegin;
895785d1243SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundariesLocal;
8963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
897785d1243SStefano Zampini }
898785d1243SStefano Zampini 
899da1bb401SStefano Zampini /*@
900f1580f4eSBarry Smith   PCBDDCGetDirichletBoundariesLocal - Get parallel `IS` for Dirichlet boundaries (in local ordering)
901da1bb401SStefano Zampini 
902785d1243SStefano Zampini   Collective
903da1bb401SStefano Zampini 
904f1580f4eSBarry Smith   Input Parameter:
90528509bceSStefano Zampini . pc - the preconditioning context
906da1bb401SStefano Zampini 
907f1580f4eSBarry Smith   Output Parameter:
90828509bceSStefano Zampini . DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
909da1bb401SStefano Zampini 
910da1bb401SStefano Zampini   Level: intermediate
911da1bb401SStefano Zampini 
912f1580f4eSBarry Smith   Note:
913f1580f4eSBarry Smith   The `IS` returned could be the same passed in earlier by the user (if provided with `PCBDDCSetDirichletBoundariesLocal()`)
914f1580f4eSBarry Smith   or a global-to-local map of the global `IS` (if provided with `PCBDDCSetDirichletBoundaries()`).
915f1580f4eSBarry Smith   In the latter case, the `IS` will be available only after `PCSetUp()`.
916da1bb401SStefano Zampini 
917562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCGetDirichletBoundaries()`, `PCBDDCSetDirichletBoundaries()`
918da1bb401SStefano Zampini @*/
919d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc, IS *DirichletBoundaries)
920d71ae5a4SJacob Faibussowitsch {
921da1bb401SStefano Zampini   PetscFunctionBegin;
922da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
923cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetDirichletBoundariesLocal_C", (PC, IS *), (pc, DirichletBoundaries));
9243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
925da1bb401SStefano Zampini }
9261e6b0712SBarry Smith 
927d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc, IS *NeumannBoundaries)
928d71ae5a4SJacob Faibussowitsch {
92953cdbc3dSStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
93053cdbc3dSStefano Zampini 
93153cdbc3dSStefano Zampini   PetscFunctionBegin;
93253cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
9333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
93453cdbc3dSStefano Zampini }
9351e6b0712SBarry Smith 
93653cdbc3dSStefano Zampini /*@
937f1580f4eSBarry Smith   PCBDDCGetNeumannBoundaries - Get parallel `IS` for Neumann boundaries
93853cdbc3dSStefano Zampini 
939f1580f4eSBarry Smith   Not Collective
940785d1243SStefano Zampini 
941f1580f4eSBarry Smith   Input Parameter:
942785d1243SStefano Zampini . pc - the preconditioning context
943785d1243SStefano Zampini 
944f1580f4eSBarry Smith   Output Parameter:
945785d1243SStefano Zampini . NeumannBoundaries - index set defining the Neumann boundaries
946785d1243SStefano Zampini 
947785d1243SStefano Zampini   Level: intermediate
948785d1243SStefano Zampini 
949f1580f4eSBarry Smith   Note:
950f1580f4eSBarry Smith   The `IS` returned (if any) is the same passed in earlier by the user with `PCBDDCSetNeumannBoundaries()`
951785d1243SStefano Zampini 
952562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCGetDirichletBoundaries()`, `PCBDDCSetDirichletBoundaries()`
953785d1243SStefano Zampini @*/
954d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc, IS *NeumannBoundaries)
955d71ae5a4SJacob Faibussowitsch {
956785d1243SStefano Zampini   PetscFunctionBegin;
957785d1243SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
958cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetNeumannBoundaries_C", (PC, IS *), (pc, NeumannBoundaries));
9593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
960785d1243SStefano Zampini }
961785d1243SStefano Zampini 
962d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc, IS *NeumannBoundaries)
963d71ae5a4SJacob Faibussowitsch {
964785d1243SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
965785d1243SStefano Zampini 
966785d1243SStefano Zampini   PetscFunctionBegin;
967785d1243SStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundariesLocal;
9683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
969785d1243SStefano Zampini }
970785d1243SStefano Zampini 
97153cdbc3dSStefano Zampini /*@
972f1580f4eSBarry Smith   PCBDDCGetNeumannBoundariesLocal - Get parallel `IS` for Neumann boundaries (in local ordering)
97353cdbc3dSStefano Zampini 
974f1580f4eSBarry Smith   Not Collective
97553cdbc3dSStefano Zampini 
976f1580f4eSBarry Smith   Input Parameter:
97728509bceSStefano Zampini . pc - the preconditioning context
97853cdbc3dSStefano Zampini 
979f1580f4eSBarry Smith   Output Parameter:
98028509bceSStefano Zampini . NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
98153cdbc3dSStefano Zampini 
98253cdbc3dSStefano Zampini   Level: intermediate
98353cdbc3dSStefano Zampini 
984f1580f4eSBarry Smith   Note:
985f1580f4eSBarry Smith   The `IS` returned could be the same passed in earlier by the user (if provided with `PCBDDCSetNeumannBoundariesLocal()`
986f1580f4eSBarry Smith   or a global-to-local map of the global `IS` (if provided with `PCBDDCSetNeumannBoundaries()`).
987f1580f4eSBarry Smith   In the latter case, the `IS` will be available after `PCSetUp()`.
98853cdbc3dSStefano Zampini 
989562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCSetNeumannBoundariesLocal)`, `PCBDDCGetNeumannBoundaries()`
99053cdbc3dSStefano Zampini @*/
991d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc, IS *NeumannBoundaries)
992d71ae5a4SJacob Faibussowitsch {
99353cdbc3dSStefano Zampini   PetscFunctionBegin;
99453cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
995cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetNeumannBoundariesLocal_C", (PC, IS *), (pc, NeumannBoundaries));
9963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9970c7d97c5SJed Brown }
9981e6b0712SBarry Smith 
999d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs, const PetscInt xadj[], const PetscInt adjncy[], PetscCopyMode copymode)
1000d71ae5a4SJacob Faibussowitsch {
100136e030ebSStefano Zampini   PC_BDDC    *pcbddc    = (PC_BDDC *)pc->data;
1002da1bb401SStefano Zampini   PCBDDCGraph mat_graph = pcbddc->mat_graph;
100356282151SStefano Zampini   PetscBool   same_data = PETSC_FALSE;
100436e030ebSStefano Zampini 
100536e030ebSStefano Zampini   PetscFunctionBegin;
10068687889aSStefano Zampini   if (!nvtxs) {
100704194a47SStefano Zampini     if (copymode == PETSC_OWN_POINTER) {
10089566063dSJacob Faibussowitsch       PetscCall(PetscFree(xadj));
10099566063dSJacob Faibussowitsch       PetscCall(PetscFree(adjncy));
101004194a47SStefano Zampini     }
10119566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphResetCSR(mat_graph));
10123ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
10138687889aSStefano Zampini   }
101466da6bd7Sstefano_zampini   if (mat_graph->nvtxs == nvtxs && mat_graph->freecsr) { /* we own the data */
101556282151SStefano Zampini     if (mat_graph->xadj == xadj && mat_graph->adjncy == adjncy) same_data = PETSC_TRUE;
101656282151SStefano Zampini     if (!same_data && mat_graph->xadj[nvtxs] == xadj[nvtxs]) {
10179566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(xadj, mat_graph->xadj, nvtxs + 1, &same_data));
101848a46eb9SPierre Jolivet       if (same_data) PetscCall(PetscArraycmp(adjncy, mat_graph->adjncy, xadj[nvtxs], &same_data));
101956282151SStefano Zampini     }
102056282151SStefano Zampini   }
102156282151SStefano Zampini   if (!same_data) {
1022674ae819SStefano Zampini     /* free old CSR */
10239566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphResetCSR(mat_graph));
1024674ae819SStefano Zampini     /* get CSR into graph structure */
1025da1bb401SStefano Zampini     if (copymode == PETSC_COPY_VALUES) {
10269566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvtxs + 1, &mat_graph->xadj));
10279566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(xadj[nvtxs], &mat_graph->adjncy));
10289566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(mat_graph->xadj, xadj, nvtxs + 1));
10299566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(mat_graph->adjncy, adjncy, xadj[nvtxs]));
1030a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1031da1bb401SStefano Zampini     } else if (copymode == PETSC_OWN_POINTER) {
10321a83f524SJed Brown       mat_graph->xadj    = (PetscInt *)xadj;
10331a83f524SJed Brown       mat_graph->adjncy  = (PetscInt *)adjncy;
1034a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1035a1dbd327SStefano Zampini     } else if (copymode == PETSC_USE_POINTER) {
1036a1dbd327SStefano Zampini       mat_graph->xadj    = (PetscInt *)xadj;
1037a1dbd327SStefano Zampini       mat_graph->adjncy  = (PetscInt *)adjncy;
1038a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_FALSE;
103963a3b9bcSJacob Faibussowitsch     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported copy mode %d", copymode);
1040575ad6abSStefano Zampini     mat_graph->nvtxs_csr         = nvtxs;
104156282151SStefano Zampini     pcbddc->recompute_topography = PETSC_TRUE;
104256282151SStefano Zampini   }
10433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
104436e030ebSStefano Zampini }
10451e6b0712SBarry Smith 
104636e030ebSStefano Zampini /*@
104754fffbccSStefano Zampini   PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local degrees of freedom.
104836e030ebSStefano Zampini 
104936e030ebSStefano Zampini   Not collective
105036e030ebSStefano Zampini 
105136e030ebSStefano Zampini   Input Parameters:
105254fffbccSStefano Zampini + pc       - the preconditioning context.
105354fffbccSStefano Zampini . nvtxs    - number of local vertices of the graph (i.e., the number of local dofs).
105404c3f3b8SBarry Smith . xadj     - CSR format row pointers for the connectivity of the dofs
105504c3f3b8SBarry Smith . adjncy   - CSR format column pointers for the connectivity of the dofs
1056f1580f4eSBarry Smith - copymode - supported modes are `PETSC_COPY_VALUES`, `PETSC_USE_POINTER` or `PETSC_OWN_POINTER`.
105736e030ebSStefano Zampini 
105836e030ebSStefano Zampini   Level: intermediate
105936e030ebSStefano Zampini 
1060f1580f4eSBarry Smith   Note:
106195452b02SPatrick Sanan   A dof is considered connected with all local dofs if xadj[dof+1]-xadj[dof] == 1 and adjncy[xadj[dof]] is negative.
106236e030ebSStefano Zampini 
1063562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PetscCopyMode`
106436e030ebSStefano Zampini @*/
1065d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc, PetscInt nvtxs, const PetscInt xadj[], const PetscInt adjncy[], PetscCopyMode copymode)
1066d71ae5a4SJacob Faibussowitsch {
10670a545947SLisandro Dalcin   void (*f)(void) = NULL;
106836e030ebSStefano Zampini 
106936e030ebSStefano Zampini   PetscFunctionBegin;
107036e030ebSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
10718687889aSStefano Zampini   if (nvtxs) {
10724f572ea9SToby Isaac     PetscAssertPointer(xadj, 3);
10734f572ea9SToby Isaac     if (xadj[nvtxs]) PetscAssertPointer(adjncy, 4);
10748687889aSStefano Zampini   }
1075cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetLocalAdjacencyGraph_C", (PC, PetscInt, const PetscInt[], const PetscInt[], PetscCopyMode), (pc, nvtxs, xadj, adjncy, copymode));
1076575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
10779566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", &f));
1078575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
10799566063dSJacob Faibussowitsch     PetscCall(PetscFree(xadj));
10809566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjncy));
1081da1bb401SStefano Zampini   }
10823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
108336e030ebSStefano Zampini }
10841e6b0712SBarry Smith 
1085d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc, PetscInt n_is, IS ISForDofs[])
1086d71ae5a4SJacob Faibussowitsch {
108763602bcaSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC *)pc->data;
108863602bcaSStefano Zampini   PetscInt  i;
108956282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
109063602bcaSStefano Zampini 
109163602bcaSStefano Zampini   PetscFunctionBegin;
109256282151SStefano Zampini   if (pcbddc->n_ISForDofsLocal == n_is) {
109356282151SStefano Zampini     for (i = 0; i < n_is; i++) {
109456282151SStefano Zampini       PetscBool isequalt;
10959566063dSJacob Faibussowitsch       PetscCall(ISEqual(ISForDofs[i], pcbddc->ISForDofsLocal[i], &isequalt));
109656282151SStefano Zampini       if (!isequalt) break;
109756282151SStefano Zampini     }
109856282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
109956282151SStefano Zampini   }
110048a46eb9SPierre Jolivet   for (i = 0; i < n_is; i++) PetscCall(PetscObjectReference((PetscObject)ISForDofs[i]));
110163602bcaSStefano Zampini   /* Destroy ISes if they were already set */
110248a46eb9SPierre Jolivet   for (i = 0; i < pcbddc->n_ISForDofsLocal; i++) PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i]));
11039566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofsLocal));
1104a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
110548a46eb9SPierre Jolivet   for (i = 0; i < pcbddc->n_ISForDofs; i++) PetscCall(ISDestroy(&pcbddc->ISForDofs[i]));
11069566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofs));
110763602bcaSStefano Zampini   pcbddc->n_ISForDofs = 0;
110863602bcaSStefano Zampini   /* allocate space then set */
110948a46eb9SPierre Jolivet   if (n_is) PetscCall(PetscMalloc1(n_is, &pcbddc->ISForDofsLocal));
1110ad540459SPierre Jolivet   for (i = 0; i < n_is; i++) pcbddc->ISForDofsLocal[i] = ISForDofs[i];
111163602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = n_is;
111263602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
111356282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
11143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
111563602bcaSStefano Zampini }
111663602bcaSStefano Zampini 
111763602bcaSStefano Zampini /*@
111898ad52f2SBarry Smith   PCBDDCSetDofsSplittingLocal - Set the `IS` defining fields of the local subdomain matrix
111963602bcaSStefano Zampini 
112063602bcaSStefano Zampini   Collective
112163602bcaSStefano Zampini 
112263602bcaSStefano Zampini   Input Parameters:
112363602bcaSStefano Zampini + pc        - the preconditioning context
112498ad52f2SBarry Smith . n_is      - number of index sets defining the fields, must be the same on all MPI processes
1125f1580f4eSBarry Smith - ISForDofs - array of `IS` describing the fields in local ordering
112663602bcaSStefano Zampini 
112763602bcaSStefano Zampini   Level: intermediate
112863602bcaSStefano Zampini 
1129f1580f4eSBarry Smith   Note:
1130feefa0e1SJacob Faibussowitsch   Not all nodes need to be listed, unlisted nodes will belong to the complement field.
113163602bcaSStefano Zampini 
1132562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDofsSplitting()`
113363602bcaSStefano Zampini @*/
1134d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc, PetscInt n_is, IS ISForDofs[])
1135d71ae5a4SJacob Faibussowitsch {
113663602bcaSStefano Zampini   PetscInt i;
113763602bcaSStefano Zampini 
113863602bcaSStefano Zampini   PetscFunctionBegin;
113963602bcaSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
114063602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc, n_is, 2);
114163602bcaSStefano Zampini   for (i = 0; i < n_is; i++) {
114263602bcaSStefano Zampini     PetscCheckSameComm(pc, 1, ISForDofs[i], 3);
114363602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i], IS_CLASSID, 3);
114463602bcaSStefano Zampini   }
1145cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDofsSplittingLocal_C", (PC, PetscInt, IS[]), (pc, n_is, ISForDofs));
11463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
114763602bcaSStefano Zampini }
114863602bcaSStefano Zampini 
1149d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc, PetscInt n_is, IS ISForDofs[])
1150d71ae5a4SJacob Faibussowitsch {
11519c0446d6SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC *)pc->data;
11529c0446d6SStefano Zampini   PetscInt  i;
115356282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
11549c0446d6SStefano Zampini 
11559c0446d6SStefano Zampini   PetscFunctionBegin;
115656282151SStefano Zampini   if (pcbddc->n_ISForDofs == n_is) {
115756282151SStefano Zampini     for (i = 0; i < n_is; i++) {
115856282151SStefano Zampini       PetscBool isequalt;
11599566063dSJacob Faibussowitsch       PetscCall(ISEqual(ISForDofs[i], pcbddc->ISForDofs[i], &isequalt));
116056282151SStefano Zampini       if (!isequalt) break;
116156282151SStefano Zampini     }
116256282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
116356282151SStefano Zampini   }
116448a46eb9SPierre Jolivet   for (i = 0; i < n_is; i++) PetscCall(PetscObjectReference((PetscObject)ISForDofs[i]));
1165da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
116648a46eb9SPierre Jolivet   for (i = 0; i < pcbddc->n_ISForDofs; i++) PetscCall(ISDestroy(&pcbddc->ISForDofs[i]));
11679566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofs));
1168a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
116948a46eb9SPierre Jolivet   for (i = 0; i < pcbddc->n_ISForDofsLocal; i++) PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i]));
11709566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofsLocal));
117163602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = 0;
1172da1bb401SStefano Zampini   /* allocate space then set */
117348a46eb9SPierre Jolivet   if (n_is) PetscCall(PetscMalloc1(n_is, &pcbddc->ISForDofs));
1174ad540459SPierre Jolivet   for (i = 0; i < n_is; i++) pcbddc->ISForDofs[i] = ISForDofs[i];
11759c0446d6SStefano Zampini   pcbddc->n_ISForDofs = n_is;
117663602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
117756282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
11783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11799c0446d6SStefano Zampini }
11801e6b0712SBarry Smith 
11819c0446d6SStefano Zampini /*@
118298ad52f2SBarry Smith   PCBDDCSetDofsSplitting - Set the `IS` defining fields of the global matrix
11839c0446d6SStefano Zampini 
118463602bcaSStefano Zampini   Collective
11859c0446d6SStefano Zampini 
11869c0446d6SStefano Zampini   Input Parameters:
11879c0446d6SStefano Zampini + pc        - the preconditioning context
11880f202f7eSStefano Zampini . n_is      - number of index sets defining the fields
118998ad52f2SBarry Smith - ISForDofs - array of `IS` describing the fields in global ordering
11909c0446d6SStefano Zampini 
11919c0446d6SStefano Zampini   Level: intermediate
11929c0446d6SStefano Zampini 
1193f1580f4eSBarry Smith   Note:
11940f202f7eSStefano Zampini   Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
11959c0446d6SStefano Zampini 
1196562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDofsSplittingLocal()`
11979c0446d6SStefano Zampini @*/
1198d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDofsSplitting(PC pc, PetscInt n_is, IS ISForDofs[])
1199d71ae5a4SJacob Faibussowitsch {
12002b510759SStefano Zampini   PetscInt i;
12019c0446d6SStefano Zampini 
12029c0446d6SStefano Zampini   PetscFunctionBegin;
12039c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
120463602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc, n_is, 2);
12052b510759SStefano Zampini   for (i = 0; i < n_is; i++) {
120663602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i], IS_CLASSID, 3);
1207a011d5a7Sstefano_zampini     PetscCheckSameComm(pc, 1, ISForDofs[i], 3);
12082b510759SStefano Zampini   }
1209cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDofsSplitting_C", (PC, PetscInt, IS[]), (pc, n_is, ISForDofs));
12103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12119c0446d6SStefano Zampini }
1212906d46d4SStefano Zampini 
1213534831adSStefano Zampini /*
1214534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
1215534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
12169c0446d6SStefano Zampini 
1217534831adSStefano Zampini    Input Parameter:
1218966d8056SPierre Jolivet +  pc - the preconditioner context
1219534831adSStefano Zampini 
1220f1580f4eSBarry Smith    Note:
1221534831adSStefano Zampini      The interface routine PCPreSolve() is not usually called directly by
1222534831adSStefano Zampini    the user, but instead is called by KSPSolve().
1223534831adSStefano Zampini */
1224d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1225d71ae5a4SJacob Faibussowitsch {
1226534831adSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC *)pc->data;
1227534831adSStefano Zampini   PC_IS    *pcis   = (PC_IS *)(pc->data);
12283972b0daSStefano Zampini   Vec       used_vec;
1229fcb54b1cSPierre Jolivet   PetscBool iscg, save_rhs = PETSC_TRUE, benign_correction_computed;
1230534831adSStefano Zampini 
1231534831adSStefano Zampini   PetscFunctionBegin;
12321f4df5f7SStefano Zampini   /* if we are working with CG, one dirichlet solve can be avoided during Krylov iterations */
123385c4d303SStefano Zampini   if (ksp) {
1234fcb54b1cSPierre Jolivet     PetscCall(PetscObjectTypeCompareAny((PetscObject)ksp, &iscg, KSPCG, KSPGROPPCG, KSPPIPECG, KSPPIPELCG, KSPPIPECGRR, ""));
123548a46eb9SPierre Jolivet     if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || !iscg || pc->mat != pc->pmat) PetscCall(PCBDDCSetUseExactDirichlet(pc, PETSC_FALSE));
123685c4d303SStefano Zampini   }
123748a46eb9SPierre Jolivet   if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || pc->mat != pc->pmat) PetscCall(PCBDDCSetUseExactDirichlet(pc, PETSC_FALSE));
12381f4df5f7SStefano Zampini 
123985c4d303SStefano Zampini   /* Creates parallel work vectors used in presolve */
124048a46eb9SPierre Jolivet   if (!pcbddc->original_rhs) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->original_rhs));
124148a46eb9SPierre Jolivet   if (!pcbddc->temp_solution) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->temp_solution));
12428d00608fSStefano Zampini 
124327b6a85dSStefano Zampini   pcbddc->temp_solution_used = PETSC_FALSE;
12443972b0daSStefano Zampini   if (x) {
12459566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)x));
12463972b0daSStefano Zampini     used_vec = x;
12478d00608fSStefano Zampini   } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */
12489566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pcbddc->temp_solution));
12493972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
12509566063dSJacob Faibussowitsch     PetscCall(VecSet(used_vec, 0.0));
125127b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
12529566063dSJacob Faibussowitsch     PetscCall(VecCopy(rhs, pcbddc->original_rhs));
1253266e20e9SStefano Zampini     save_rhs                  = PETSC_FALSE;
1254266e20e9SStefano Zampini     pcbddc->eliminate_dirdofs = PETSC_TRUE;
12553972b0daSStefano Zampini   }
12568efcfb23SStefano Zampini 
12578efcfb23SStefano Zampini   /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */
12583972b0daSStefano Zampini   if (ksp) {
1259a0cb1b98SStefano Zampini     /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */
12609566063dSJacob Faibussowitsch     PetscCall(KSPGetInitialGuessNonzero(ksp, &pcbddc->ksp_guess_nonzero));
126148a46eb9SPierre Jolivet     if (!pcbddc->ksp_guess_nonzero) PetscCall(VecSet(used_vec, 0.0));
12623972b0daSStefano Zampini   }
12633308cffdSStefano Zampini 
12648d00608fSStefano Zampini   pcbddc->rhs_change = PETSC_FALSE;
12653972b0daSStefano Zampini   /* Take into account zeroed rows -> change rhs and store solution removed */
126670c64980SStefano Zampini   if (rhs && pcbddc->eliminate_dirdofs) {
12673975b054SStefano Zampini     IS dirIS = NULL;
12683975b054SStefano Zampini 
1269a07ea27aSStefano Zampini     /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */
12709566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph, &dirIS));
12713975b054SStefano Zampini     if (dirIS) {
1272906d46d4SStefano Zampini       Mat_IS            *matis = (Mat_IS *)pc->pmat->data;
1273785d1243SStefano Zampini       PetscInt           dirsize, i, *is_indices;
12742b095fd8SStefano Zampini       PetscScalar       *array_x;
12752b095fd8SStefano Zampini       const PetscScalar *array_diagonal;
1276785d1243SStefano Zampini 
12779566063dSJacob Faibussowitsch       PetscCall(MatGetDiagonal(pc->pmat, pcis->vec1_global));
12789566063dSJacob Faibussowitsch       PetscCall(VecPointwiseDivide(pcis->vec1_global, rhs, pcis->vec1_global));
12799566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_global, pcis->vec2_N, INSERT_VALUES, SCATTER_FORWARD));
12809566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_global, pcis->vec2_N, INSERT_VALUES, SCATTER_FORWARD));
12819566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx, used_vec, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD));
12829566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx, used_vec, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD));
12839566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(dirIS, &dirsize));
12849566063dSJacob Faibussowitsch       PetscCall(VecGetArray(pcis->vec1_N, &array_x));
12859566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(pcis->vec2_N, &array_diagonal));
12869566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(dirIS, (const PetscInt **)&is_indices));
12872fa5cd67SKarl Rupp       for (i = 0; i < dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
12889566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(dirIS, (const PetscInt **)&is_indices));
12899566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(pcis->vec2_N, &array_diagonal));
12909566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(pcis->vec1_N, &array_x));
12919566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_N, used_vec, INSERT_VALUES, SCATTER_REVERSE));
12929566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_N, used_vec, INSERT_VALUES, SCATTER_REVERSE));
12938d00608fSStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
12949566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&dirIS));
12958efcfb23SStefano Zampini     }
1296a07ea27aSStefano Zampini   }
1297b76ba322SStefano Zampini 
12988efcfb23SStefano Zampini   /* remove the computed solution or the initial guess from the rhs */
12998d00608fSStefano Zampini   if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero)) {
130027b6a85dSStefano Zampini     /* save the original rhs */
130127b6a85dSStefano Zampini     if (save_rhs) {
13029566063dSJacob Faibussowitsch       PetscCall(VecSwap(rhs, pcbddc->original_rhs));
130327b6a85dSStefano Zampini       save_rhs = PETSC_FALSE;
13048d00608fSStefano Zampini     }
13058d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
13069566063dSJacob Faibussowitsch     PetscCall(VecScale(used_vec, -1.0));
13079566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(pc->mat, used_vec, pcbddc->original_rhs, rhs));
13089566063dSJacob Faibussowitsch     PetscCall(VecScale(used_vec, -1.0));
13099566063dSJacob Faibussowitsch     PetscCall(VecCopy(used_vec, pcbddc->temp_solution));
131027b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
13111baa6e33SBarry Smith     if (ksp) PetscCall(KSPSetInitialGuessNonzero(ksp, PETSC_FALSE));
13123308cffdSStefano Zampini   }
13139566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&used_vec));
1314b76ba322SStefano Zampini 
1315fc17d649SStefano Zampini   /* compute initial vector in benign space if needed
131627b6a85dSStefano Zampini      and remove non-benign solution from the rhs */
131727b6a85dSStefano Zampini   benign_correction_computed = PETSC_FALSE;
131808af2428SStefano Zampini   if (rhs && pcbddc->benign_compute_correction && (pcbddc->benign_have_null || pcbddc->benign_apply_coarse_only)) {
13191f4df5f7SStefano Zampini     /* compute u^*_h using ideas similar to those in Xuemin Tu's PhD thesis (see Section 4.8.1)
13201f4df5f7SStefano Zampini        Recursively apply BDDC in the multilevel case */
132148a46eb9SPierre Jolivet     if (!pcbddc->benign_vec) PetscCall(VecDuplicate(rhs, &pcbddc->benign_vec));
1322c69e9cc1SStefano Zampini     /* keep applying coarse solver unless we no longer have benign subdomains */
1323c69e9cc1SStefano Zampini     pcbddc->benign_apply_coarse_only = pcbddc->benign_have_null ? PETSC_TRUE : PETSC_FALSE;
132427b6a85dSStefano Zampini     if (!pcbddc->benign_skip_correction) {
13259566063dSJacob Faibussowitsch       PetscCall(PCApply_BDDC(pc, rhs, pcbddc->benign_vec));
13263bca92a6SStefano Zampini       benign_correction_computed = PETSC_TRUE;
13271baa6e33SBarry Smith       if (pcbddc->temp_solution_used) PetscCall(VecAXPY(pcbddc->temp_solution, 1.0, pcbddc->benign_vec));
13289566063dSJacob Faibussowitsch       PetscCall(VecScale(pcbddc->benign_vec, -1.0));
132927b6a85dSStefano Zampini       /* store the original rhs if not done earlier */
13301baa6e33SBarry Smith       if (save_rhs) PetscCall(VecSwap(rhs, pcbddc->original_rhs));
133127b6a85dSStefano Zampini       if (pcbddc->rhs_change) {
13329566063dSJacob Faibussowitsch         PetscCall(MatMultAdd(pc->mat, pcbddc->benign_vec, rhs, rhs));
133327b6a85dSStefano Zampini       } else {
13349566063dSJacob Faibussowitsch         PetscCall(MatMultAdd(pc->mat, pcbddc->benign_vec, pcbddc->original_rhs, rhs));
133527b6a85dSStefano Zampini       }
13360369aaf7SStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
133727b6a85dSStefano Zampini     }
133827b6a85dSStefano Zampini     pcbddc->benign_apply_coarse_only = PETSC_FALSE;
13394df7a6bfSStefano Zampini   } else {
13409566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&pcbddc->benign_vec));
13410369aaf7SStefano Zampini   }
13422d4c4fecSStefano Zampini 
13432d4c4fecSStefano Zampini   /* dbg output */
1344a198735bSStefano Zampini   if (pcbddc->dbg_flag && benign_correction_computed) {
13451f4df5f7SStefano Zampini     Vec v;
1346c69e9cc1SStefano Zampini 
13479566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_global, &v));
1348c69e9cc1SStefano Zampini     if (pcbddc->ChangeOfBasisMatrix) {
13499566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, rhs, v));
1350c69e9cc1SStefano Zampini     } else {
13519566063dSJacob Faibussowitsch       PetscCall(VecCopy(rhs, v));
1352c69e9cc1SStefano Zampini     }
13539566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, v, PETSC_TRUE));
135463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "LEVEL %" PetscInt_FMT ": is the correction benign?\n", pcbddc->current_level));
13559566063dSJacob Faibussowitsch     PetscCall(PetscScalarView(pcbddc->benign_n, pcbddc->benign_p0, pcbddc->dbg_viewer));
13569566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
13579566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&v));
13581f4df5f7SStefano Zampini   }
13590369aaf7SStefano Zampini 
13600369aaf7SStefano Zampini   /* set initial guess if using PCG */
13618ae0ca82SStefano Zampini   pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
13620369aaf7SStefano Zampini   if (x && pcbddc->use_exact_dirichlet_trick) {
13639566063dSJacob Faibussowitsch     PetscCall(VecSet(x, 0.0));
13641dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
136527b6a85dSStefano Zampini       if (benign_correction_computed) { /* we have already saved the changed rhs */
13669566063dSJacob Faibussowitsch         PetscCall(VecLockReadPop(pcis->vec1_global));
13671dd7afcfSStefano Zampini       } else {
13689566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, rhs, pcis->vec1_global));
13691dd7afcfSStefano Zampini       }
13709566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_global, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
13719566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_global, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
13721dd7afcfSStefano Zampini     } else {
13739566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D, rhs, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
13749566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D, rhs, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
13751dd7afcfSStefano Zampini     }
13769566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
13779566063dSJacob Faibussowitsch     PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D));
13789566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
13799566063dSJacob Faibussowitsch     PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D));
13801dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
13819566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_global, 0.));
13829566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, pcis->vec1_global, INSERT_VALUES, SCATTER_REVERSE));
13839566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, pcis->vec1_global, INSERT_VALUES, SCATTER_REVERSE));
13849566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcis->vec1_global, x));
13851dd7afcfSStefano Zampini     } else {
13869566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, x, INSERT_VALUES, SCATTER_REVERSE));
13879566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, x, INSERT_VALUES, SCATTER_REVERSE));
13881dd7afcfSStefano Zampini     }
13891baa6e33SBarry Smith     if (ksp) PetscCall(KSPSetInitialGuessNonzero(ksp, PETSC_TRUE));
13908ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_TRUE;
1391266e20e9SStefano Zampini   } else if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior && benign_correction_computed && pcbddc->use_exact_dirichlet_trick) {
13929566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(pcis->vec1_global));
13930369aaf7SStefano Zampini   }
13943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1395534831adSStefano Zampini }
1396906d46d4SStefano Zampini 
1397534831adSStefano Zampini /*
1398534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
1399534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
1400534831adSStefano Zampini 
1401534831adSStefano Zampini    Input Parameter:
1402966d8056SPierre Jolivet +  pc - the preconditioner context
1403534831adSStefano Zampini 
1404534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
1405534831adSStefano Zampini 
1406f1580f4eSBarry Smith    Note:
1407534831adSStefano Zampini      The interface routine PCPostSolve() is not usually called directly by
1408534831adSStefano Zampini      the user, but instead is called by KSPSolve().
1409534831adSStefano Zampini */
1410d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1411d71ae5a4SJacob Faibussowitsch {
1412534831adSStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
1413534831adSStefano Zampini 
1414534831adSStefano Zampini   PetscFunctionBegin;
14153972b0daSStefano Zampini   /* add solution removed in presolve */
14166bcfc461SStefano Zampini   if (x && pcbddc->rhs_change) {
141727b6a85dSStefano Zampini     if (pcbddc->temp_solution_used) {
14189566063dSJacob Faibussowitsch       PetscCall(VecAXPY(x, 1.0, pcbddc->temp_solution));
1419af140850Sstefano_zampini     } else if (pcbddc->benign_compute_correction && pcbddc->benign_vec) {
14209566063dSJacob Faibussowitsch       PetscCall(VecAXPY(x, -1.0, pcbddc->benign_vec));
14213425bc38SStefano Zampini     }
1422af140850Sstefano_zampini     /* restore to original state (not for FETI-DP) */
1423af140850Sstefano_zampini     if (ksp) pcbddc->temp_solution_used = PETSC_FALSE;
142427b6a85dSStefano Zampini   }
142527b6a85dSStefano Zampini 
1426266e20e9SStefano Zampini   /* restore rhs to its original state (not needed for FETI-DP) */
14278d00608fSStefano Zampini   if (rhs && pcbddc->rhs_change) {
14289566063dSJacob Faibussowitsch     PetscCall(VecSwap(rhs, pcbddc->original_rhs));
14298d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_FALSE;
1430af140850Sstefano_zampini   }
14318efcfb23SStefano Zampini   /* restore ksp guess state */
14328efcfb23SStefano Zampini   if (ksp) {
14339566063dSJacob Faibussowitsch     PetscCall(KSPSetInitialGuessNonzero(ksp, pcbddc->ksp_guess_nonzero));
14348ae0ca82SStefano Zampini     /* reset flag for exact dirichlet trick */
14358ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
1436af140850Sstefano_zampini   }
14373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1438534831adSStefano Zampini }
1439af140850Sstefano_zampini 
144004c3f3b8SBarry Smith // PetscClangLinter pragma disable: -fdoc-sowing-chars
14410c7d97c5SJed Brown /*
14420c7d97c5SJed Brown   PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
14430c7d97c5SJed Brown   by setting data structures and options.
14440c7d97c5SJed Brown 
14450c7d97c5SJed Brown   Input Parameter:
1446feefa0e1SJacob Faibussowitsch . pc - the preconditioner context
14470c7d97c5SJed Brown 
14480c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
14490c7d97c5SJed Brown 
14500c7d97c5SJed Brown */
145166976f2fSJacob Faibussowitsch static PetscErrorCode PCSetUp_BDDC(PC pc)
1452d71ae5a4SJacob Faibussowitsch {
14530c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC *)pc->data;
1454c703fcc7SStefano Zampini   PCBDDCSubSchurs sub_schurs;
14555e8657edSStefano Zampini   Mat_IS         *matis;
145608122e43SStefano Zampini   MatNullSpace    nearnullspace;
145735509ce9Sstefano_zampini   Mat             lA;
145835509ce9Sstefano_zampini   IS              lP, zerodiag = NULL;
145991e8d312SStefano Zampini   PetscInt        nrows, ncols;
146086bfa4cfSStefano Zampini   PetscMPIInt     size;
1461c703fcc7SStefano Zampini   PetscBool       computesubschurs;
14628de1fae6SStefano Zampini   PetscBool       computeconstraintsmatrix;
14633b03f7bbSStefano Zampini   PetscBool       new_nearnullspace_provided, ismatis, rl;
1464b94d7dedSBarry Smith   PetscBool       isset, issym, isspd;
14650c7d97c5SJed Brown 
14660c7d97c5SJed Brown   PetscFunctionBegin;
14679566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATIS, &ismatis));
146828b400f6SJacob Faibussowitsch   PetscCheck(ismatis, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "PCBDDC preconditioner requires matrix of type MATIS");
14699566063dSJacob Faibussowitsch   PetscCall(MatGetSize(pc->pmat, &nrows, &ncols));
14707827d75bSBarry Smith   PetscCheck(nrows == ncols, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "PCBDDC preconditioner requires a square preconditioning matrix");
14719566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
147286bfa4cfSStefano Zampini 
14735e8657edSStefano Zampini   matis = (Mat_IS *)pc->pmat->data;
1474f4ddd8eeSStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */
14753b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
147671582508SStefano Zampini      Also, BDDC builds its own KSP for the Dirichlet problem */
14773b03f7bbSStefano Zampini   rl = pcbddc->recompute_topography;
14783b03f7bbSStefano Zampini   if (!pc->setupcalled || pc->flag == DIFFERENT_NONZERO_PATTERN) rl = PETSC_TRUE;
14791c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&rl, &pcbddc->recompute_topography, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc)));
1480c83e1ba7SStefano Zampini   if (pcbddc->recompute_topography) {
1481c83e1ba7SStefano Zampini     pcbddc->graphanalyzed    = PETSC_FALSE;
1482c83e1ba7SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1483c83e1ba7SStefano Zampini   } else {
14848de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_FALSE;
1485c83e1ba7SStefano Zampini   }
1486b087196eSStefano Zampini 
1487b087196eSStefano Zampini   /* check parameters' compatibility */
1488b7ab4a40SStefano Zampini   if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE;
1489bd2a564bSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_threshold[0] != 0.0 || pcbddc->adaptive_threshold[1] != 0.0);
149086bfa4cfSStefano Zampini   pcbddc->use_deluxe_scaling   = (PetscBool)(pcbddc->use_deluxe_scaling && size > 1);
149186bfa4cfSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_selection && size > 1);
1492bf3a8328SStefano Zampini   pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined);
1493862806e4SStefano Zampini   if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE;
1494862806e4SStefano Zampini 
14955a95e1ceSStefano Zampini   computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling);
149616909a7fSStefano Zampini 
149771582508SStefano Zampini   /* activate all connected components if the netflux has been requested */
1498bb05f991SStefano Zampini   if (pcbddc->compute_nonetflux) {
1499bb05f991SStefano Zampini     pcbddc->use_vertices = PETSC_TRUE;
1500bb05f991SStefano Zampini     pcbddc->use_edges    = PETSC_TRUE;
1501bb05f991SStefano Zampini     pcbddc->use_faces    = PETSC_TRUE;
1502bb05f991SStefano Zampini   }
1503bb05f991SStefano Zampini 
1504f4ddd8eeSStefano Zampini   /* Get stdout for dbg */
150570cf5478SStefano Zampini   if (pcbddc->dbg_flag) {
1506ad540459SPierre Jolivet     if (!pcbddc->dbg_viewer) pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc));
15079566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer));
15089566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIAddTab(pcbddc->dbg_viewer, 2 * pcbddc->current_level));
1509f4ddd8eeSStefano Zampini   }
1510f4ddd8eeSStefano Zampini 
1511c703fcc7SStefano Zampini   /* process topology information */
15129566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Topology[pcbddc->current_level], pc, 0, 0, 0));
151371582508SStefano Zampini   if (pcbddc->recompute_topography) {
15149566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeLocalTopologyInfo(pc));
15151baa6e33SBarry Smith     if (pcbddc->discretegradient) PetscCall(PCBDDCNedelecSupport(pc));
1516c703fcc7SStefano Zampini   }
15174f819b78SStefano Zampini   if (pcbddc->corner_selected) pcbddc->use_vertices = PETSC_TRUE;
1518a13144ffSStefano Zampini 
1519c703fcc7SStefano Zampini   /* change basis if requested by the user */
15205e8657edSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) {
15215e8657edSStefano Zampini     /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */
15225e8657edSStefano Zampini     pcbddc->use_change_of_basis = PETSC_FALSE;
15239566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeLocalMatrix(pc, pcbddc->user_ChangeOfBasisMatrix));
15245e8657edSStefano Zampini   } else {
15259566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcbddc->local_mat));
15269566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)matis->A));
15275e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
1528d16cbb6bSStefano Zampini   }
1529d16cbb6bSStefano Zampini 
15304f1b2e48SStefano Zampini   /*
1531c703fcc7SStefano Zampini      Compute change of basis on local pressures (aka zerodiag dofs) with the benign trick
15324f1b2e48SStefano Zampini      This should come earlier then PCISSetUp for extracting the correct subdomain matrices
15334f1b2e48SStefano Zampini   */
15349566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignShellMat(pc, PETSC_TRUE));
1535d16cbb6bSStefano Zampini   if (pcbddc->benign_saddle_point) {
15369f47a83aSStefano Zampini     PC_IS *pcis = (PC_IS *)pc->data;
15379f47a83aSStefano Zampini 
153805b28244SStefano Zampini     if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE;
15393b03f7bbSStefano Zampini     /* detect local saddle point and change the basis in pcbddc->local_mat */
15409566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignDetectSaddlePoint(pc, (PetscBool)(!pcbddc->recompute_topography), &zerodiag));
1541a3df083aSStefano Zampini     /* pop B0 mat from local mat */
15429566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignPopOrPushB0(pc, PETSC_TRUE));
15431dd7afcfSStefano Zampini     /* give pcis a hint to not reuse submatrices during PCISCreate */
15441dd7afcfSStefano Zampini     if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) {
15451dd7afcfSStefano Zampini       if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) {
15461dd7afcfSStefano Zampini         pcis->reusesubmatrices = PETSC_FALSE;
15471dd7afcfSStefano Zampini       } else {
1548a3df083aSStefano Zampini         pcis->reusesubmatrices = PETSC_TRUE;
15491dd7afcfSStefano Zampini       }
1550a3df083aSStefano Zampini     } else {
15519f47a83aSStefano Zampini       pcis->reusesubmatrices = PETSC_FALSE;
1552674ae819SStefano Zampini     }
1553a3df083aSStefano Zampini   }
155427b6a85dSStefano Zampini 
15558037d520SStefano Zampini   /* propagate relevant information */
1556b94d7dedSBarry Smith   PetscCall(MatIsSymmetricKnown(matis->A, &isset, &issym));
1557b94d7dedSBarry Smith   if (isset) PetscCall(MatSetOption(pcbddc->local_mat, MAT_SYMMETRIC, issym));
1558b94d7dedSBarry Smith   PetscCall(MatIsSPDKnown(matis->A, &isset, &isspd));
1559b94d7dedSBarry Smith   if (isset) PetscCall(MatSetOption(pcbddc->local_mat, MAT_SPD, isspd));
1560e496cd5dSStefano Zampini 
15615e8657edSStefano Zampini   /* Set up all the "iterative substructuring" common block without computing solvers */
15625e8657edSStefano Zampini   {
15635e8657edSStefano Zampini     Mat temp_mat;
15645e8657edSStefano Zampini 
15655e8657edSStefano Zampini     temp_mat = matis->A;
15665e8657edSStefano Zampini     matis->A = pcbddc->local_mat;
15679566063dSJacob Faibussowitsch     PetscCall(PCISSetUp(pc, PETSC_TRUE, PETSC_FALSE));
15685e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
15695e8657edSStefano Zampini     matis->A          = temp_mat;
15705e8657edSStefano Zampini   }
1571684f6988SStefano Zampini 
157281d14e9dSStefano Zampini   /* Analyze interface */
157364ac59b8SStefano Zampini   if (!pcbddc->graphanalyzed) {
15749566063dSJacob Faibussowitsch     PetscCall(PCBDDCAnalyzeInterface(pc));
15758de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
15760fdf79fbSJacob Faibussowitsch     PetscCheck(!(pcbddc->adaptive_selection && !pcbddc->use_deluxe_scaling && !pcbddc->mat_graph->twodim), PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Cannot compute the adaptive primal space for a problem with 3D edges without deluxe scaling");
1577a198735bSStefano Zampini     if (pcbddc->compute_nonetflux) {
1578669cc0f4SStefano Zampini       MatNullSpace nnfnnsp;
1579669cc0f4SStefano Zampini 
158028b400f6SJacob Faibussowitsch       PetscCheck(pcbddc->divudotp, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Missing divudotp operator");
15819566063dSJacob Faibussowitsch       PetscCall(PCBDDCComputeNoNetFlux(pc->pmat, pcbddc->divudotp, pcbddc->divudotp_trans, pcbddc->divudotp_vl2l, pcbddc->mat_graph, &nnfnnsp));
158271582508SStefano Zampini       /* TODO what if a nearnullspace is already attached? */
15838037d520SStefano Zampini       if (nnfnnsp) {
15849566063dSJacob Faibussowitsch         PetscCall(MatSetNearNullSpace(pc->pmat, nnfnnsp));
15859566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceDestroy(&nnfnnsp));
1586669cc0f4SStefano Zampini       }
1587674ae819SStefano Zampini     }
15888037d520SStefano Zampini   }
15899566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Topology[pcbddc->current_level], pc, 0, 0, 0));
1590fb8d54d4SStefano Zampini 
15915408967cSStefano Zampini   /* check existence of a divergence free extension, i.e.
15925408967cSStefano Zampini      b(v_I,p_0) = 0 for all v_I (raise error if not).
15935408967cSStefano Zampini      Also, check that PCBDDCBenignGetOrSetP0 works */
159448a46eb9SPierre Jolivet   if (pcbddc->benign_saddle_point && pcbddc->dbg_flag > 1) PetscCall(PCBDDCBenignCheck(pc, zerodiag));
15959566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&zerodiag));
159606f24817SStefano Zampini 
1597b96c3477SStefano Zampini   /* Setup local dirichlet solver ksp_D and sub_schurs solvers */
159848a46eb9SPierre Jolivet   if (computesubschurs && pcbddc->recompute_topography) PetscCall(PCBDDCInitSubSchurs(pc));
15999d54b7f4SStefano Zampini   /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/
160048a46eb9SPierre Jolivet   if (!pcbddc->use_deluxe_scaling) PetscCall(PCBDDCScalingSetUp(pc));
1601c703fcc7SStefano Zampini 
1602c703fcc7SStefano Zampini   /* finish setup solvers and do adaptive selection of constraints */
1603b334f244SStefano Zampini   sub_schurs = pcbddc->sub_schurs;
1604b334f244SStefano Zampini   if (sub_schurs && sub_schurs->schur_explicit) {
16051baa6e33SBarry Smith     if (computesubschurs) PetscCall(PCBDDCSetUpSubSchurs(pc));
16069566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetUpLocalSolvers(pc, PETSC_TRUE, PETSC_FALSE));
1607d5574798SStefano Zampini   } else {
16089566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetUpLocalSolvers(pc, PETSC_TRUE, PETSC_FALSE));
16091baa6e33SBarry Smith     if (computesubschurs) PetscCall(PCBDDCSetUpSubSchurs(pc));
16102070dbb6SStefano Zampini   }
161108122e43SStefano Zampini   if (pcbddc->adaptive_selection) {
16129566063dSJacob Faibussowitsch     PetscCall(PCBDDCAdaptiveSelection(pc));
16138de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1614b7eb3628SStefano Zampini   }
1615684f6988SStefano Zampini 
1616f4ddd8eeSStefano Zampini   /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */
1617fb8d54d4SStefano Zampini   new_nearnullspace_provided = PETSC_FALSE;
16189566063dSJacob Faibussowitsch   PetscCall(MatGetNearNullSpace(pc->pmat, &nearnullspace));
1619f4ddd8eeSStefano Zampini   if (pcbddc->onearnullspace) { /* already used nearnullspace */
1620f4ddd8eeSStefano Zampini     if (!nearnullspace) {       /* near null space attached to mat has been destroyed */
1621f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1622f4ddd8eeSStefano Zampini     } else {
1623f4ddd8eeSStefano Zampini       /* determine if the two nullspaces are different (should be lightweight) */
1624f4ddd8eeSStefano Zampini       if (nearnullspace != pcbddc->onearnullspace) {
1625f4ddd8eeSStefano Zampini         new_nearnullspace_provided = PETSC_TRUE;
1626165b64e2SStefano Zampini       } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */
1627f4ddd8eeSStefano Zampini         PetscInt         i;
1628165b64e2SStefano Zampini         const Vec       *nearnullvecs;
1629165b64e2SStefano Zampini         PetscObjectState state;
1630165b64e2SStefano Zampini         PetscInt         nnsp_size;
16319566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceGetVecs(nearnullspace, NULL, &nnsp_size, &nearnullvecs));
1632f4ddd8eeSStefano Zampini         for (i = 0; i < nnsp_size; i++) {
16339566063dSJacob Faibussowitsch           PetscCall(PetscObjectStateGet((PetscObject)nearnullvecs[i], &state));
1634165b64e2SStefano Zampini           if (pcbddc->onearnullvecs_state[i] != state) {
1635f4ddd8eeSStefano Zampini             new_nearnullspace_provided = PETSC_TRUE;
1636f4ddd8eeSStefano Zampini             break;
1637f4ddd8eeSStefano Zampini           }
1638f4ddd8eeSStefano Zampini         }
1639f4ddd8eeSStefano Zampini       }
1640f4ddd8eeSStefano Zampini     }
1641f4ddd8eeSStefano Zampini   } else {
1642f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* both nearnullspaces are null */
1643f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_FALSE;
1644f4ddd8eeSStefano Zampini     } else { /* nearnullspace attached later */
1645f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1646f4ddd8eeSStefano Zampini     }
1647f4ddd8eeSStefano Zampini   }
1648f4ddd8eeSStefano Zampini 
1649f4ddd8eeSStefano Zampini   /* Setup constraints and related work vectors */
1650727cdba6SStefano Zampini   /* reset primal space flags */
16519566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_LocalWork[pcbddc->current_level], pc, 0, 0, 0));
1652f4ddd8eeSStefano Zampini   pcbddc->new_primal_space       = PETSC_FALSE;
1653727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_FALSE;
16548de1fae6SStefano Zampini   if (computeconstraintsmatrix || new_nearnullspace_provided) {
1655727cdba6SStefano Zampini     /* It also sets the primal space flags */
16569566063dSJacob Faibussowitsch     PetscCall(PCBDDCConstraintsSetUp(pc));
16579543d0ffSStefano Zampini   }
1658e7b262bdSStefano Zampini   /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */
16599566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetUpLocalWorkVectors(pc));
16605e8657edSStefano Zampini 
16615e8657edSStefano Zampini   if (pcbddc->use_change_of_basis) {
16625e8657edSStefano Zampini     PC_IS *pcis = (PC_IS *)(pc->data);
16635e8657edSStefano Zampini 
16649566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeLocalMatrix(pc, pcbddc->ChangeOfBasisMatrix));
16654f1b2e48SStefano Zampini     if (pcbddc->benign_change) {
16669566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcbddc->benign_B0));
1667c263805aSStefano Zampini       /* pop B0 from pcbddc->local_mat */
16689566063dSJacob Faibussowitsch       PetscCall(PCBDDCBenignPopOrPushB0(pc, PETSC_TRUE));
1669c263805aSStefano Zampini     }
16705e8657edSStefano Zampini     /* get submatrices */
16719566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_IB));
16729566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_BI));
16739566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_BB));
16749566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_B_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &pcis->A_BB));
16759566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_I_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &pcis->A_IB));
16769566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_B_local, pcis->is_I_local, MAT_INITIAL_MATRIX, &pcis->A_BI));
16773975b054SStefano Zampini     /* set flag in pcis to not reuse submatrices during PCISCreate */
16783975b054SStefano Zampini     pcis->reusesubmatrices = PETSC_FALSE;
16799c6a02ceSStefano Zampini   } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) {
16809566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcbddc->local_mat));
16819566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)matis->A));
16825e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
16835e8657edSStefano Zampini   }
168435509ce9Sstefano_zampini 
168535509ce9Sstefano_zampini   /* interface pressure block row for B_C */
16869566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lP", (PetscObject *)&lP));
16879566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lA", (PetscObject *)&lA));
168835509ce9Sstefano_zampini   if (lA && lP) {
168935509ce9Sstefano_zampini     PC_IS    *pcis = (PC_IS *)pc->data;
169035509ce9Sstefano_zampini     Mat       B_BI, B_BB, Bt_BI, Bt_BB;
169135509ce9Sstefano_zampini     PetscBool issym;
1692b94d7dedSBarry Smith 
16939566063dSJacob Faibussowitsch     PetscCall(MatIsSymmetric(lA, PETSC_SMALL, &issym));
16946cc1294bSstefano_zampini     if (issym) {
16959566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_I_local, MAT_INITIAL_MATRIX, &B_BI));
16969566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_B_local, MAT_INITIAL_MATRIX, &B_BB));
16979566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(B_BI, &Bt_BI));
16989566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(B_BB, &Bt_BB));
169935509ce9Sstefano_zampini     } else {
17009566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_I_local, MAT_INITIAL_MATRIX, &B_BI));
17019566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_B_local, MAT_INITIAL_MATRIX, &B_BB));
17029566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, pcis->is_I_local, lP, MAT_INITIAL_MATRIX, &Bt_BI));
17039566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, pcis->is_B_local, lP, MAT_INITIAL_MATRIX, &Bt_BB));
170435509ce9Sstefano_zampini     }
17059566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_B_BI", (PetscObject)B_BI));
17069566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_B_BB", (PetscObject)B_BB));
17079566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_Bt_BI", (PetscObject)Bt_BI));
17089566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_Bt_BB", (PetscObject)Bt_BB));
17099566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B_BI));
17109566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B_BB));
17119566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Bt_BI));
17129566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Bt_BB));
171335509ce9Sstefano_zampini   }
17149566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_LocalWork[pcbddc->current_level], pc, 0, 0, 0));
171535509ce9Sstefano_zampini 
1716b96c3477SStefano Zampini   /* SetUp coarse and local Neumann solvers */
17179566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetUpSolvers(pc));
1718b96c3477SStefano Zampini   /* SetUp Scaling operator */
17191baa6e33SBarry Smith   if (pcbddc->use_deluxe_scaling) PetscCall(PCBDDCScalingSetUp(pc));
1720c703fcc7SStefano Zampini 
17211dd7afcfSStefano Zampini   /* mark topography as done */
172256282151SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
17230369aaf7SStefano Zampini 
17241dd7afcfSStefano Zampini   /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */
17259566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignShellMat(pc, PETSC_FALSE));
17261dd7afcfSStefano Zampini 
172758a03d70SStefano Zampini   if (pcbddc->dbg_flag) {
17289566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISubtractTab(pcbddc->dbg_viewer, 2 * pcbddc->current_level));
17299566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer));
17302b510759SStefano Zampini   }
17313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17320c7d97c5SJed Brown }
17330c7d97c5SJed Brown 
173404c3f3b8SBarry Smith // PetscClangLinter pragma disable: -fdoc-sowing-chars
17350c7d97c5SJed Brown /*
173650efa1b5SStefano Zampini    PCApply_BDDC - Applies the BDDC operator to a vector.
17370c7d97c5SJed Brown 
17380c7d97c5SJed Brown    Input Parameters:
17390f202f7eSStefano Zampini +  pc - the preconditioner context
17400f202f7eSStefano Zampini -  r - input vector (global)
17410c7d97c5SJed Brown 
17420c7d97c5SJed Brown    Output Parameter:
17430c7d97c5SJed Brown .  z - output vector (global)
17440c7d97c5SJed Brown 
17450c7d97c5SJed Brown    Application Interface Routine: PCApply()
17460c7d97c5SJed Brown  */
174766976f2fSJacob Faibussowitsch static PetscErrorCode PCApply_BDDC(PC pc, Vec r, Vec z)
1748d71ae5a4SJacob Faibussowitsch {
17490c7d97c5SJed Brown   PC_IS            *pcis   = (PC_IS *)(pc->data);
17500c7d97c5SJed Brown   PC_BDDC          *pcbddc = (PC_BDDC *)(pc->data);
1751b3338236SStefano Zampini   Mat               lA     = NULL;
1752b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
17533b03a366Sstefano_zampini   const PetscScalar one   = 1.0;
17543b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
17552617d88aSStefano Zampini   const PetscScalar zero  = 0.0;
17560c7d97c5SJed Brown   /* This code is similar to that provided in nn.c for PCNN
17570c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
1758b097fa66SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */
17590c7d97c5SJed Brown 
17600c7d97c5SJed Brown   PetscFunctionBegin;
17619566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(citation, &cited));
176248a46eb9SPierre Jolivet   if (pcbddc->switch_static) PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat, &lA));
1763b3338236SStefano Zampini 
17641dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
17651dd7afcfSStefano Zampini     Vec swap;
176627b6a85dSStefano Zampini 
17679566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, r, pcbddc->work_change));
17681dd7afcfSStefano Zampini     swap                = pcbddc->work_change;
17691dd7afcfSStefano Zampini     pcbddc->work_change = r;
17701dd7afcfSStefano Zampini     r                   = swap;
17711dd7afcfSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
17729cc2a9b1Sstefano_zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) {
17739566063dSJacob Faibussowitsch       PetscCall(VecCopy(r, pcis->vec1_global));
17749566063dSJacob Faibussowitsch       PetscCall(VecLockReadPush(pcis->vec1_global));
17751dd7afcfSStefano Zampini     }
17761dd7afcfSStefano Zampini   }
177727b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
17789566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, r, PETSC_TRUE));
1779efc2fbd9SStefano Zampini   }
1780bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET && !pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
17819566063dSJacob Faibussowitsch     PetscCall(VecCopy(r, z));
17820c7d97c5SJed Brown     /* First Dirichlet solve */
17839566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
17849566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
17850c7d97c5SJed Brown     /*
17860c7d97c5SJed Brown       Assembling right hand side for BDDC operator
1787b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
1788674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
17890c7d97c5SJed Brown     */
17909566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
1791*a1cb837bSStefano Zampini     if (n_D) {
17929566063dSJacob Faibussowitsch       PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D));
17939566063dSJacob Faibussowitsch       PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
17949566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D));
17959566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec2_D, m_one));
179616909a7fSStefano Zampini       if (pcbddc->switch_static) {
17979566063dSJacob Faibussowitsch         PetscCall(VecSet(pcis->vec1_N, 0.));
17989566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
17999566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
180016909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
18019566063dSJacob Faibussowitsch           PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N));
180216909a7fSStefano Zampini         } else {
18039566063dSJacob Faibussowitsch           PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
18049566063dSJacob Faibussowitsch           PetscCall(MatMult(lA, pcis->vec2_N, pcis->vec1_N));
18059566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
180616909a7fSStefano Zampini         }
18079566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD));
18089566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD));
18099566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
18109566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
181116909a7fSStefano Zampini       } else {
18129566063dSJacob Faibussowitsch         PetscCall(MatMult(pcis->A_BI, pcis->vec2_D, pcis->vec1_B));
181316909a7fSStefano Zampini       }
1814b097fa66SStefano Zampini     } else {
1815*a1cb837bSStefano Zampini       PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
18169566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_B, zero));
1817b097fa66SStefano Zampini     }
18189566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE));
18199566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE));
18209566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingRestriction(pc, z, pcis->vec1_B));
1821b76ba322SStefano Zampini   } else {
182248a46eb9SPierre Jolivet     if (!pcbddc->benign_apply_coarse_only) PetscCall(PCBDDCScalingRestriction(pc, r, pcis->vec1_B));
18234fee134fSStefano Zampini   }
1824bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) {
182528b400f6SJacob Faibussowitsch     PetscCheck(pcbddc->switch_static, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "You forgot to pass -pc_bddc_switch_static");
18269566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
18279566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
1828bc960bbfSJed Brown   }
1829b76ba322SStefano Zampini 
18302617d88aSStefano Zampini   /* Apply interface preconditioner
18312617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
18329566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(pc, PETSC_FALSE));
18332617d88aSStefano Zampini 
1834674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
18359566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(pc, pcis->vec1_B, z));
1836bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) {
18379566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_D, z, INSERT_VALUES, SCATTER_REVERSE));
18389566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_D, z, INSERT_VALUES, SCATTER_REVERSE));
18393ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1840bc960bbfSJed Brown   }
18413b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
18429566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
18439566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
1844b097fa66SStefano Zampini   if (n_B) {
184516909a7fSStefano Zampini     if (pcbddc->switch_static) {
18469566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
18479566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
18489566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
18499566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
185016909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
18519566063dSJacob Faibussowitsch         PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N));
185216909a7fSStefano Zampini       } else {
18539566063dSJacob Faibussowitsch         PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
18549566063dSJacob Faibussowitsch         PetscCall(MatMult(lA, pcis->vec2_N, pcis->vec1_N));
18559566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
185616909a7fSStefano Zampini       }
18579566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD));
18589566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD));
185916909a7fSStefano Zampini     } else {
18609566063dSJacob Faibussowitsch       PetscCall(MatMult(pcis->A_IB, pcis->vec1_B, pcis->vec3_D));
186116909a7fSStefano Zampini     }
186216909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
186316909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
18649566063dSJacob Faibussowitsch       PetscCall(MatMult(lA, pcis->vec1_D, pcis->vec3_D));
186516909a7fSStefano Zampini     } else {
18669566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_D, pcis->vec1_N));
18679566063dSJacob Faibussowitsch       PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N));
18689566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec2_N, pcis->vec3_D));
186916909a7fSStefano Zampini     }
1870b097fa66SStefano Zampini   }
18719566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
18729566063dSJacob Faibussowitsch   PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec3_D, pcis->vec4_D));
18739566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
18749566063dSJacob Faibussowitsch   PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec4_D));
1875efc2fbd9SStefano Zampini 
18768ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1877b097fa66SStefano Zampini     if (pcbddc->switch_static) {
18789566063dSJacob Faibussowitsch       PetscCall(VecAXPBYPCZ(pcis->vec2_D, m_one, one, m_one, pcis->vec4_D, pcis->vec1_D));
1879b097fa66SStefano Zampini     } else {
18809566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec2_D, m_one, m_one, pcis->vec4_D));
1881b097fa66SStefano Zampini     }
18829566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE));
18839566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE));
1884b097fa66SStefano Zampini   } else {
1885b097fa66SStefano Zampini     if (pcbddc->switch_static) {
18869566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec4_D, one, m_one, pcis->vec1_D));
1887b097fa66SStefano Zampini     } else {
18889566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec4_D, m_one));
1889b097fa66SStefano Zampini     }
18909566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE));
18919566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE));
1892b097fa66SStefano Zampini   }
189327b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
18941baa6e33SBarry Smith     if (pcbddc->benign_apply_coarse_only) PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n));
18959566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, z, PETSC_FALSE));
1896efc2fbd9SStefano Zampini   }
18971f4df5f7SStefano Zampini 
18981dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1899f913dca9SStefano Zampini     pcbddc->work_change = r;
19009566063dSJacob Faibussowitsch     PetscCall(VecCopy(z, pcbddc->work_change));
19019566063dSJacob Faibussowitsch     PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcbddc->work_change, z));
19021dd7afcfSStefano Zampini   }
19033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19040c7d97c5SJed Brown }
190550efa1b5SStefano Zampini 
190650efa1b5SStefano Zampini /*
190750efa1b5SStefano Zampini    PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector.
190850efa1b5SStefano Zampini 
190950efa1b5SStefano Zampini    Input Parameters:
19100f202f7eSStefano Zampini +  pc - the preconditioner context
19110f202f7eSStefano Zampini -  r - input vector (global)
191250efa1b5SStefano Zampini 
191350efa1b5SStefano Zampini    Output Parameter:
191450efa1b5SStefano Zampini .  z - output vector (global)
191550efa1b5SStefano Zampini 
191650efa1b5SStefano Zampini    Application Interface Routine: PCApplyTranspose()
191750efa1b5SStefano Zampini  */
191866976f2fSJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_BDDC(PC pc, Vec r, Vec z)
1919d71ae5a4SJacob Faibussowitsch {
192050efa1b5SStefano Zampini   PC_IS            *pcis   = (PC_IS *)(pc->data);
192150efa1b5SStefano Zampini   PC_BDDC          *pcbddc = (PC_BDDC *)(pc->data);
1922b3338236SStefano Zampini   Mat               lA     = NULL;
1923b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
192450efa1b5SStefano Zampini   const PetscScalar one   = 1.0;
192550efa1b5SStefano Zampini   const PetscScalar m_one = -1.0;
192650efa1b5SStefano Zampini   const PetscScalar zero  = 0.0;
192750efa1b5SStefano Zampini 
192850efa1b5SStefano Zampini   PetscFunctionBegin;
19299566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(citation, &cited));
193048a46eb9SPierre Jolivet   if (pcbddc->switch_static) PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat, &lA));
19311dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
19321dd7afcfSStefano Zampini     Vec swap;
193327b6a85dSStefano Zampini 
19349566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, r, pcbddc->work_change));
19351dd7afcfSStefano Zampini     swap                = pcbddc->work_change;
19361dd7afcfSStefano Zampini     pcbddc->work_change = r;
19371dd7afcfSStefano Zampini     r                   = swap;
193827b6a85dSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
19398ae0ca82SStefano Zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->exact_dirichlet_trick_app && pcbddc->change_interior) {
19409566063dSJacob Faibussowitsch       PetscCall(VecCopy(r, pcis->vec1_global));
19419566063dSJacob Faibussowitsch       PetscCall(VecLockReadPush(pcis->vec1_global));
19421dd7afcfSStefano Zampini     }
194327b6a85dSStefano Zampini   }
194427b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
19459566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, r, PETSC_TRUE));
1946537c1cdfSStefano Zampini   }
19478ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
19489566063dSJacob Faibussowitsch     PetscCall(VecCopy(r, z));
194950efa1b5SStefano Zampini     /* First Dirichlet solve */
19509566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
19519566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
195250efa1b5SStefano Zampini     /*
195350efa1b5SStefano Zampini       Assembling right hand side for BDDC operator
1954b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
195550efa1b5SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
195650efa1b5SStefano Zampini     */
1957b097fa66SStefano Zampini     if (n_D) {
19589566063dSJacob Faibussowitsch       PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
19599566063dSJacob Faibussowitsch       PetscCall(KSPSolveTranspose(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D));
19609566063dSJacob Faibussowitsch       PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
19619566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D));
19629566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec2_D, m_one));
196316909a7fSStefano Zampini       if (pcbddc->switch_static) {
19649566063dSJacob Faibussowitsch         PetscCall(VecSet(pcis->vec1_N, 0.));
19659566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
19669566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
196716909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
19689566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N));
196916909a7fSStefano Zampini         } else {
19709566063dSJacob Faibussowitsch           PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
19719566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(lA, pcis->vec2_N, pcis->vec1_N));
19729566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
197316909a7fSStefano Zampini         }
19749566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD));
19759566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD));
19769566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
19779566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
197816909a7fSStefano Zampini       } else {
19799566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcis->A_IB, pcis->vec2_D, pcis->vec1_B));
198016909a7fSStefano Zampini       }
1981b097fa66SStefano Zampini     } else {
19829566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_B, zero));
1983b097fa66SStefano Zampini     }
19849566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE));
19859566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE));
19869566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingRestriction(pc, z, pcis->vec1_B));
198750efa1b5SStefano Zampini   } else {
19889566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingRestriction(pc, r, pcis->vec1_B));
198950efa1b5SStefano Zampini   }
199050efa1b5SStefano Zampini 
199150efa1b5SStefano Zampini   /* Apply interface preconditioner
199250efa1b5SStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
19939566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(pc, PETSC_TRUE));
199450efa1b5SStefano Zampini 
199550efa1b5SStefano Zampini   /* Apply transpose of partition of unity operator */
19969566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(pc, pcis->vec1_B, z));
199750efa1b5SStefano Zampini 
199850efa1b5SStefano Zampini   /* Second Dirichlet solve and assembling of output */
19999566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
20009566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
2001b097fa66SStefano Zampini   if (n_B) {
200216909a7fSStefano Zampini     if (pcbddc->switch_static) {
20039566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
20049566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
20059566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
20069566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
200716909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
20089566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N));
200916909a7fSStefano Zampini       } else {
20109566063dSJacob Faibussowitsch         PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
20119566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(lA, pcis->vec2_N, pcis->vec1_N));
20129566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
201316909a7fSStefano Zampini       }
20149566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD));
20159566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD));
201616909a7fSStefano Zampini     } else {
20179566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcis->A_BI, pcis->vec1_B, pcis->vec3_D));
201816909a7fSStefano Zampini     }
201916909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
202016909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
20219566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(lA, pcis->vec1_D, pcis->vec3_D));
202216909a7fSStefano Zampini     } else {
20239566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_D, pcis->vec1_N));
20249566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N));
20259566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec2_N, pcis->vec3_D));
202616909a7fSStefano Zampini     }
2027b097fa66SStefano Zampini   }
20289566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
20299566063dSJacob Faibussowitsch   PetscCall(KSPSolveTranspose(pcbddc->ksp_D, pcis->vec3_D, pcis->vec4_D));
20309566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
20319566063dSJacob Faibussowitsch   PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec4_D));
20328ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
2033b097fa66SStefano Zampini     if (pcbddc->switch_static) {
20349566063dSJacob Faibussowitsch       PetscCall(VecAXPBYPCZ(pcis->vec2_D, m_one, one, m_one, pcis->vec4_D, pcis->vec1_D));
2035b097fa66SStefano Zampini     } else {
20369566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec2_D, m_one, m_one, pcis->vec4_D));
2037b097fa66SStefano Zampini     }
20389566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE));
20399566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE));
2040b097fa66SStefano Zampini   } else {
2041b097fa66SStefano Zampini     if (pcbddc->switch_static) {
20429566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec4_D, one, m_one, pcis->vec1_D));
2043b097fa66SStefano Zampini     } else {
20449566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec4_D, m_one));
2045b097fa66SStefano Zampini     }
20469566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE));
20479566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE));
2048b097fa66SStefano Zampini   }
204927b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
20509566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, z, PETSC_FALSE));
2051537c1cdfSStefano Zampini   }
20521dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2053f913dca9SStefano Zampini     pcbddc->work_change = r;
20549566063dSJacob Faibussowitsch     PetscCall(VecCopy(z, pcbddc->work_change));
20559566063dSJacob Faibussowitsch     PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcbddc->work_change, z));
20561dd7afcfSStefano Zampini   }
20573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
205850efa1b5SStefano Zampini }
2059674ae819SStefano Zampini 
206066976f2fSJacob Faibussowitsch static PetscErrorCode PCReset_BDDC(PC pc)
2061d71ae5a4SJacob Faibussowitsch {
2062da1bb401SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
20639326c5c6Sstefano_zampini   PC_IS   *pcis   = (PC_IS *)pc->data;
20649326c5c6Sstefano_zampini   KSP      kspD, kspR, kspC;
2065da1bb401SStefano Zampini 
2066da1bb401SStefano Zampini   PetscFunctionBegin;
2067674ae819SStefano Zampini   /* free BDDC custom data  */
20689566063dSJacob Faibussowitsch   PetscCall(PCBDDCResetCustomization(pc));
2069674ae819SStefano Zampini   /* destroy objects related to topography */
20709566063dSJacob Faibussowitsch   PetscCall(PCBDDCResetTopography(pc));
207134a97f8cSStefano Zampini   /* destroy objects for scaling operator */
20729566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingDestroy(pc));
2073674ae819SStefano Zampini   /* free solvers stuff */
20749566063dSJacob Faibussowitsch   PetscCall(PCBDDCResetSolvers(pc));
207562a6ff1dSStefano Zampini   /* free global vectors needed in presolve */
20769566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->temp_solution));
20779566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->original_rhs));
20781dd7afcfSStefano Zampini   /* free data created by PCIS */
207904c3f3b8SBarry Smith   PetscCall(PCISReset(pc));
20809326c5c6Sstefano_zampini 
20819326c5c6Sstefano_zampini   /* restore defaults */
20829326c5c6Sstefano_zampini   kspD = pcbddc->ksp_D;
20839326c5c6Sstefano_zampini   kspR = pcbddc->ksp_R;
20849326c5c6Sstefano_zampini   kspC = pcbddc->coarse_ksp;
20859566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(pc->data, sizeof(*pcbddc)));
20869326c5c6Sstefano_zampini   pcis->n_neigh                     = -1;
20879326c5c6Sstefano_zampini   pcis->scaling_factor              = 1.0;
20889326c5c6Sstefano_zampini   pcis->reusesubmatrices            = PETSC_TRUE;
20899326c5c6Sstefano_zampini   pcbddc->use_local_adj             = PETSC_TRUE;
20909326c5c6Sstefano_zampini   pcbddc->use_vertices              = PETSC_TRUE;
20919326c5c6Sstefano_zampini   pcbddc->use_edges                 = PETSC_TRUE;
20929326c5c6Sstefano_zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
20939326c5c6Sstefano_zampini   pcbddc->vertex_size               = 1;
20949326c5c6Sstefano_zampini   pcbddc->recompute_topography      = PETSC_TRUE;
20959326c5c6Sstefano_zampini   pcbddc->coarse_size               = -1;
20969326c5c6Sstefano_zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
20979326c5c6Sstefano_zampini   pcbddc->coarsening_ratio          = 8;
20989326c5c6Sstefano_zampini   pcbddc->coarse_eqs_per_proc       = 1;
20999326c5c6Sstefano_zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
21009326c5c6Sstefano_zampini   pcbddc->nedfield                  = -1;
21019326c5c6Sstefano_zampini   pcbddc->nedglobal                 = PETSC_TRUE;
21029326c5c6Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
21039326c5c6Sstefano_zampini   pcbddc->sub_schurs_layers         = -1;
21049326c5c6Sstefano_zampini   pcbddc->ksp_D                     = kspD;
21059326c5c6Sstefano_zampini   pcbddc->ksp_R                     = kspR;
21069326c5c6Sstefano_zampini   pcbddc->coarse_ksp                = kspC;
21073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21089326c5c6Sstefano_zampini }
21099326c5c6Sstefano_zampini 
211066976f2fSJacob Faibussowitsch static PetscErrorCode PCDestroy_BDDC(PC pc)
2111d71ae5a4SJacob Faibussowitsch {
21129326c5c6Sstefano_zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
21139326c5c6Sstefano_zampini 
21149326c5c6Sstefano_zampini   PetscFunctionBegin;
21159566063dSJacob Faibussowitsch   PetscCall(PCReset_BDDC(pc));
21169566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcbddc->ksp_D));
21179566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcbddc->ksp_R));
21189566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcbddc->coarse_ksp));
21199566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDiscreteGradient_C", NULL));
21209566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDivergenceMat_C", NULL));
21219566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetChangeOfBasisMat_C", NULL));
21229566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesLocalIS_C", NULL));
21239566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesIS_C", NULL));
212432fe681dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesLocalIS_C", NULL));
212532fe681dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesIS_C", NULL));
21269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetCoarseningRatio_C", NULL));
21279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevel_C", NULL));
21289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetUseExactDirichlet_C", NULL));
21299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevels_C", NULL));
21309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundaries_C", NULL));
21319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundariesLocal_C", NULL));
21329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundaries_C", NULL));
21339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundariesLocal_C", NULL));
21349566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundaries_C", NULL));
21359566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundariesLocal_C", NULL));
21369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundaries_C", NULL));
21379566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundariesLocal_C", NULL));
21389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplitting_C", NULL));
21399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplittingLocal_C", NULL));
21409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", NULL));
21419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCCreateFETIDPOperators_C", NULL));
21429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetRHS_C", NULL));
21439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetSolution_C", NULL));
21449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", NULL));
21459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", NULL));
21469566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
21473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2148da1bb401SStefano Zampini }
21491e6b0712SBarry Smith 
2150d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetCoordinates_BDDC(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
2151d71ae5a4SJacob Faibussowitsch {
2152ab8c8b98SStefano Zampini   PC_BDDC    *pcbddc    = (PC_BDDC *)pc->data;
2153ab8c8b98SStefano Zampini   PCBDDCGraph mat_graph = pcbddc->mat_graph;
2154ab8c8b98SStefano Zampini 
2155ab8c8b98SStefano Zampini   PetscFunctionBegin;
21569566063dSJacob Faibussowitsch   PetscCall(PetscFree(mat_graph->coords));
21579566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nloc * dim, &mat_graph->coords));
21589566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(mat_graph->coords, coords, nloc * dim));
2159ab8c8b98SStefano Zampini   mat_graph->cnloc = nloc;
2160ab8c8b98SStefano Zampini   mat_graph->cdim  = dim;
2161ab8c8b98SStefano Zampini   mat_graph->cloc  = PETSC_FALSE;
21624f819b78SStefano Zampini   /* flg setup */
21634f819b78SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
21644f819b78SStefano Zampini   pcbddc->corner_selected      = PETSC_FALSE;
21653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2166ab8c8b98SStefano Zampini }
2167ab8c8b98SStefano Zampini 
2168d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCPreSolveChangeRHS_BDDC(PC pc, PetscBool *change)
2169d71ae5a4SJacob Faibussowitsch {
2170a06fd7f2SStefano Zampini   PetscFunctionBegin;
2171a06fd7f2SStefano Zampini   *change = PETSC_TRUE;
21723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2173a06fd7f2SStefano Zampini }
2174a06fd7f2SStefano Zampini 
2175d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
2176d71ae5a4SJacob Faibussowitsch {
2177674ae819SStefano Zampini   FETIDPMat_ctx mat_ctx;
2178266e20e9SStefano Zampini   Vec           work;
21793425bc38SStefano Zampini   PC_IS        *pcis;
21803425bc38SStefano Zampini   PC_BDDC      *pcbddc;
21810c7d97c5SJed Brown 
21823425bc38SStefano Zampini   PetscFunctionBegin;
21839566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx));
21843425bc38SStefano Zampini   pcis   = (PC_IS *)mat_ctx->pc->data;
21853425bc38SStefano Zampini   pcbddc = (PC_BDDC *)mat_ctx->pc->data;
21863425bc38SStefano Zampini 
21879566063dSJacob Faibussowitsch   PetscCall(VecSet(fetidp_flux_rhs, 0.0));
2188229984c5Sstefano_zampini   /* copy rhs since we may change it during PCPreSolve_BDDC */
218948a46eb9SPierre Jolivet   if (!pcbddc->original_rhs) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->original_rhs));
21906cc1294bSstefano_zampini   if (mat_ctx->rhs_flip) {
21919566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(pcbddc->original_rhs, standard_rhs, mat_ctx->rhs_flip));
21926cc1294bSstefano_zampini   } else {
21939566063dSJacob Faibussowitsch     PetscCall(VecCopy(standard_rhs, pcbddc->original_rhs));
21946cc1294bSstefano_zampini   }
2195af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
2196229984c5Sstefano_zampini     /* interface pressure rhs */
21979566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->g2g_p, fetidp_flux_rhs, pcbddc->original_rhs, INSERT_VALUES, SCATTER_REVERSE));
21989566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->g2g_p, fetidp_flux_rhs, pcbddc->original_rhs, INSERT_VALUES, SCATTER_REVERSE));
21999566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->g2g_p, standard_rhs, fetidp_flux_rhs, INSERT_VALUES, SCATTER_FORWARD));
22009566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->g2g_p, standard_rhs, fetidp_flux_rhs, INSERT_VALUES, SCATTER_FORWARD));
220148a46eb9SPierre Jolivet     if (!mat_ctx->rhs_flip) PetscCall(VecScale(fetidp_flux_rhs, -1.));
22026cc1294bSstefano_zampini   }
2203c08af4c6SStefano Zampini   /*
2204c08af4c6SStefano Zampini      change of basis for physical rhs if needed
2205c08af4c6SStefano Zampini      It also changes the rhs in case of dirichlet boundaries
2206c08af4c6SStefano Zampini   */
22079566063dSJacob Faibussowitsch   PetscCall(PCPreSolve_BDDC(mat_ctx->pc, NULL, pcbddc->original_rhs, NULL));
2208fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
22099566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, pcbddc->original_rhs, pcbddc->work_change));
22103738a8e6SStefano Zampini     work = pcbddc->work_change;
2211fc17d649SStefano Zampini   } else {
22123738a8e6SStefano Zampini     work = pcbddc->original_rhs;
2213fc17d649SStefano Zampini   }
22143425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
22159566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_D, work, mat_ctx->temp_solution_D, INSERT_VALUES, SCATTER_FORWARD));
22169566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_D, work, mat_ctx->temp_solution_D, INSERT_VALUES, SCATTER_FORWARD));
2217fb223d50SStefano Zampini   /* scale rhs since it should be unassembled */
2218fb223d50SStefano Zampini   /* TODO use counter scaling? (also below) */
22199566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD));
22209566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD));
2221674ae819SStefano Zampini   /* Apply partition of unity */
22229566063dSJacob Faibussowitsch   PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B, pcis->D, mat_ctx->temp_solution_B));
22239566063dSJacob Faibussowitsch   /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */
22248eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
22253425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
22269566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0));
22279566063dSJacob Faibussowitsch     PetscCall(KSPSolve(pcbddc->ksp_D, mat_ctx->temp_solution_D, pcis->vec1_D));
22289566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0));
2229c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
22309566063dSJacob Faibussowitsch     PetscCall(MatMult(pcis->A_BI, pcis->vec1_D, pcis->vec1_B));
22319566063dSJacob Faibussowitsch     PetscCall(VecAXPY(mat_ctx->temp_solution_B, -1.0, pcis->vec1_B));
22329566063dSJacob Faibussowitsch     PetscCall(VecSet(work, 0.0));
22339566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, mat_ctx->temp_solution_B, work, ADD_VALUES, SCATTER_REVERSE));
22349566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, mat_ctx->temp_solution_B, work, ADD_VALUES, SCATTER_REVERSE));
22359566063dSJacob Faibussowitsch     /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */
22369566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD));
22379566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD));
22389566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B, pcis->D, mat_ctx->temp_solution_B));
22393425bc38SStefano Zampini   }
22403425bc38SStefano Zampini   /* BDDC rhs */
22419566063dSJacob Faibussowitsch   PetscCall(VecCopy(mat_ctx->temp_solution_B, pcis->vec1_B));
22421baa6e33SBarry Smith   if (pcbddc->switch_static) PetscCall(VecCopy(mat_ctx->temp_solution_D, pcis->vec1_D));
22433425bc38SStefano Zampini   /* apply BDDC */
22449566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n));
22459566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc, PETSC_FALSE));
22469566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n));
2247229984c5Sstefano_zampini 
22483425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
22499566063dSJacob Faibussowitsch   PetscCall(MatMult(mat_ctx->B_delta, pcis->vec1_B, mat_ctx->lambda_local));
22509566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(mat_ctx->l2g_lambda, mat_ctx->lambda_local, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD));
22519566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(mat_ctx->l2g_lambda, mat_ctx->lambda_local, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD));
2252229984c5Sstefano_zampini   /* Add contribution to interface pressures */
2253229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
22549566063dSJacob Faibussowitsch     PetscCall(MatMult(mat_ctx->B_BB, pcis->vec1_B, mat_ctx->vP));
22551baa6e33SBarry Smith     if (pcbddc->switch_static) PetscCall(MatMultAdd(mat_ctx->B_BI, pcis->vec1_D, mat_ctx->vP, mat_ctx->vP));
22569566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->l2g_p, mat_ctx->vP, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD));
22579566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->l2g_p, mat_ctx->vP, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD));
2258229984c5Sstefano_zampini   }
22593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22603425bc38SStefano Zampini }
22611e6b0712SBarry Smith 
22623425bc38SStefano Zampini /*@
226398ad52f2SBarry Smith   PCBDDCMatFETIDPGetRHS - Compute the right-hand side for a FETI-DP linear system using the physical right-hand side
22643425bc38SStefano Zampini 
22653425bc38SStefano Zampini   Collective
22663425bc38SStefano Zampini 
22673425bc38SStefano Zampini   Input Parameters:
2268f1580f4eSBarry Smith + fetidp_mat   - the FETI-DP matrix object obtained by a call to `PCBDDCCreateFETIDPOperators()`
22690f202f7eSStefano Zampini - standard_rhs - the right-hand side of the original linear system
22703425bc38SStefano Zampini 
2271f1580f4eSBarry Smith   Output Parameter:
22720f202f7eSStefano Zampini . fetidp_flux_rhs - the right-hand side for the FETI-DP linear system
22733425bc38SStefano Zampini 
22743425bc38SStefano Zampini   Level: developer
22753425bc38SStefano Zampini 
2276562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCCreateFETIDPOperators()`, `PCBDDCMatFETIDPGetSolution()`
22773425bc38SStefano Zampini @*/
2278d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
2279d71ae5a4SJacob Faibussowitsch {
2280674ae819SStefano Zampini   FETIDPMat_ctx mat_ctx;
22813425bc38SStefano Zampini 
22823425bc38SStefano Zampini   PetscFunctionBegin;
2283266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat, MAT_CLASSID, 1);
2284266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_rhs, VEC_CLASSID, 2);
2285266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_rhs, VEC_CLASSID, 3);
22869566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx));
2287cac4c232SBarry Smith   PetscUseMethod(mat_ctx->pc, "PCBDDCMatFETIDPGetRHS_C", (Mat, Vec, Vec), (fetidp_mat, standard_rhs, fetidp_flux_rhs));
22883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22893425bc38SStefano Zampini }
22901e6b0712SBarry Smith 
2291d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
2292d71ae5a4SJacob Faibussowitsch {
2293674ae819SStefano Zampini   FETIDPMat_ctx mat_ctx;
22943425bc38SStefano Zampini   PC_IS        *pcis;
22953425bc38SStefano Zampini   PC_BDDC      *pcbddc;
2296229984c5Sstefano_zampini   Vec           work;
22973425bc38SStefano Zampini 
22983425bc38SStefano Zampini   PetscFunctionBegin;
22999566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx));
23003425bc38SStefano Zampini   pcis   = (PC_IS *)mat_ctx->pc->data;
23013425bc38SStefano Zampini   pcbddc = (PC_BDDC *)mat_ctx->pc->data;
23023425bc38SStefano Zampini 
23033425bc38SStefano Zampini   /* apply B_delta^T */
23049566063dSJacob Faibussowitsch   PetscCall(VecSet(pcis->vec1_B, 0.));
23059566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(mat_ctx->l2g_lambda, fetidp_flux_sol, mat_ctx->lambda_local, INSERT_VALUES, SCATTER_REVERSE));
23069566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(mat_ctx->l2g_lambda, fetidp_flux_sol, mat_ctx->lambda_local, INSERT_VALUES, SCATTER_REVERSE));
23079566063dSJacob Faibussowitsch   PetscCall(MatMultTranspose(mat_ctx->B_delta, mat_ctx->lambda_local, pcis->vec1_B));
2308229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
23099566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->l2g_p, fetidp_flux_sol, mat_ctx->vP, INSERT_VALUES, SCATTER_REVERSE));
23109566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->l2g_p, fetidp_flux_sol, mat_ctx->vP, INSERT_VALUES, SCATTER_REVERSE));
23119566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(mat_ctx->Bt_BB, mat_ctx->vP, pcis->vec1_B, pcis->vec1_B));
2312229984c5Sstefano_zampini   }
2313229984c5Sstefano_zampini 
23143425bc38SStefano Zampini   /* compute rhs for BDDC application */
23159566063dSJacob Faibussowitsch   PetscCall(VecAYPX(pcis->vec1_B, -1.0, mat_ctx->temp_solution_B));
23168eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
23179566063dSJacob Faibussowitsch     PetscCall(VecCopy(mat_ctx->temp_solution_D, pcis->vec1_D));
2318229984c5Sstefano_zampini     if (mat_ctx->l2g_p) {
23199566063dSJacob Faibussowitsch       PetscCall(VecScale(mat_ctx->vP, -1.));
23209566063dSJacob Faibussowitsch       PetscCall(MatMultAdd(mat_ctx->Bt_BI, mat_ctx->vP, pcis->vec1_D, pcis->vec1_D));
23213425bc38SStefano Zampini     }
2322229984c5Sstefano_zampini   }
2323229984c5Sstefano_zampini 
23243425bc38SStefano Zampini   /* apply BDDC */
23259566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n));
23269566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc, PETSC_FALSE));
2327229984c5Sstefano_zampini 
2328229984c5Sstefano_zampini   /* put values into global vector */
2329af140850Sstefano_zampini   if (pcbddc->ChangeOfBasisMatrix) work = pcbddc->work_change;
2330af140850Sstefano_zampini   else work = standard_sol;
23319566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, work, INSERT_VALUES, SCATTER_REVERSE));
23329566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, work, INSERT_VALUES, SCATTER_REVERSE));
23338eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
23343425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
23359566063dSJacob Faibussowitsch     PetscCall(MatMult(pcis->A_IB, pcis->vec1_B, pcis->vec1_D));
23369566063dSJacob Faibussowitsch     PetscCall(VecAYPX(pcis->vec1_D, -1.0, mat_ctx->temp_solution_D));
23379566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0));
23389566063dSJacob Faibussowitsch     PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec1_D));
23399566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0));
2340c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
23413425bc38SStefano Zampini   }
2342229984c5Sstefano_zampini 
23439566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_D, work, INSERT_VALUES, SCATTER_REVERSE));
23449566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_D, work, INSERT_VALUES, SCATTER_REVERSE));
2345266e20e9SStefano Zampini   /* add p0 solution to final solution */
23469566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignGetOrSetP0(mat_ctx->pc, work, PETSC_FALSE));
23471baa6e33SBarry Smith   if (pcbddc->ChangeOfBasisMatrix) PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, work, standard_sol));
23489566063dSJacob Faibussowitsch   PetscCall(PCPostSolve_BDDC(mat_ctx->pc, NULL, NULL, standard_sol));
2349af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
23509566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->g2g_p, fetidp_flux_sol, standard_sol, INSERT_VALUES, SCATTER_REVERSE));
23519566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->g2g_p, fetidp_flux_sol, standard_sol, INSERT_VALUES, SCATTER_REVERSE));
2352229984c5Sstefano_zampini   }
23533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23543425bc38SStefano Zampini }
23551e6b0712SBarry Smith 
2356d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_BDDCIPC(PC pc, PetscViewer viewer)
2357d71ae5a4SJacob Faibussowitsch {
23585a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
23595a1e936bSStefano Zampini   PetscBool   isascii;
23605a1e936bSStefano Zampini 
23615a1e936bSStefano Zampini   PetscFunctionBegin;
23629566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
23639566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
236448a46eb9SPierre Jolivet   if (isascii) PetscCall(PetscViewerASCIIPrintf(viewer, "BDDC interface preconditioner\n"));
23659566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushTab(viewer));
23669566063dSJacob Faibussowitsch   PetscCall(PCView(bddcipc_ctx->bddc, viewer));
23679566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopTab(viewer));
23683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23695a1e936bSStefano Zampini }
23705a1e936bSStefano Zampini 
2371d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetUp_BDDCIPC(PC pc)
2372d71ae5a4SJacob Faibussowitsch {
23735a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
23745a1e936bSStefano Zampini   PetscBool   isbddc;
23755a1e936bSStefano Zampini   Vec         vv;
23765a1e936bSStefano Zampini   IS          is;
23775a1e936bSStefano Zampini   PC_IS      *pcis;
23785a1e936bSStefano Zampini 
23795a1e936bSStefano Zampini   PetscFunctionBegin;
23809566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
23819566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)bddcipc_ctx->bddc, PCBDDC, &isbddc));
238228b400f6SJacob Faibussowitsch   PetscCheck(isbddc, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Invalid type %s. Must be of type bddc", ((PetscObject)bddcipc_ctx->bddc)->type_name);
23839566063dSJacob Faibussowitsch   PetscCall(PCSetUp(bddcipc_ctx->bddc));
23845a1e936bSStefano Zampini 
23855a1e936bSStefano Zampini   /* create interface scatter */
23865a1e936bSStefano Zampini   pcis = (PC_IS *)(bddcipc_ctx->bddc->data);
23879566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l));
23889566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(pc->pmat, &vv, NULL));
23899566063dSJacob Faibussowitsch   PetscCall(ISRenumber(pcis->is_B_global, NULL, NULL, &is));
23909566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(vv, is, pcis->vec1_B, NULL, &bddcipc_ctx->g2l));
23919566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
23929566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&vv));
23933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23945a1e936bSStefano Zampini }
23955a1e936bSStefano Zampini 
2396d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_BDDCIPC(PC pc, Vec r, Vec x)
2397d71ae5a4SJacob Faibussowitsch {
23985a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
23995a1e936bSStefano Zampini   PC_IS      *pcis;
24005a1e936bSStefano Zampini   VecScatter  tmps;
24015a1e936bSStefano Zampini 
24025a1e936bSStefano Zampini   PetscFunctionBegin;
24039566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
24045a1e936bSStefano Zampini   pcis              = (PC_IS *)(bddcipc_ctx->bddc->data);
24055a1e936bSStefano Zampini   tmps              = pcis->global_to_B;
24065a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
24079566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc, r, pcis->vec1_B));
24089566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc, PETSC_FALSE));
24099566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc, pcis->vec1_B, x));
24105a1e936bSStefano Zampini   pcis->global_to_B = tmps;
24113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24125a1e936bSStefano Zampini }
24135a1e936bSStefano Zampini 
2414d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_BDDCIPC(PC pc, Vec r, Vec x)
2415d71ae5a4SJacob Faibussowitsch {
24165a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
24175a1e936bSStefano Zampini   PC_IS      *pcis;
24185a1e936bSStefano Zampini   VecScatter  tmps;
24195a1e936bSStefano Zampini 
24205a1e936bSStefano Zampini   PetscFunctionBegin;
24219566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
24225a1e936bSStefano Zampini   pcis              = (PC_IS *)(bddcipc_ctx->bddc->data);
24235a1e936bSStefano Zampini   tmps              = pcis->global_to_B;
24245a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
24259566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc, r, pcis->vec1_B));
24269566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc, PETSC_TRUE));
24279566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc, pcis->vec1_B, x));
24285a1e936bSStefano Zampini   pcis->global_to_B = tmps;
24293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24305a1e936bSStefano Zampini }
24315a1e936bSStefano Zampini 
2432d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_BDDCIPC(PC pc)
2433d71ae5a4SJacob Faibussowitsch {
24345a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
24355a1e936bSStefano Zampini 
24365a1e936bSStefano Zampini   PetscFunctionBegin;
24379566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
24389566063dSJacob Faibussowitsch   PetscCall(PCDestroy(&bddcipc_ctx->bddc));
24399566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l));
24409566063dSJacob Faibussowitsch   PetscCall(PetscFree(bddcipc_ctx));
24413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24425a1e936bSStefano Zampini }
24435a1e936bSStefano Zampini 
24443425bc38SStefano Zampini /*@
24450f202f7eSStefano Zampini   PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system
24463425bc38SStefano Zampini 
24473425bc38SStefano Zampini   Collective
24483425bc38SStefano Zampini 
24493425bc38SStefano Zampini   Input Parameters:
245020f4b53cSBarry Smith + fetidp_mat      - the FETI-DP matrix obtained by a call to `PCBDDCCreateFETIDPOperators()`
2451f1580f4eSBarry Smith - fetidp_flux_sol - the solution of the FETI-DP linear system`
24523425bc38SStefano Zampini 
2453f1580f4eSBarry Smith   Output Parameter:
24540f202f7eSStefano Zampini . standard_sol - the solution defined on the physical domain
24553425bc38SStefano Zampini 
24563425bc38SStefano Zampini   Level: developer
24573425bc38SStefano Zampini 
2458562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCCreateFETIDPOperators()`, `PCBDDCMatFETIDPGetRHS()`
24593425bc38SStefano Zampini @*/
2460d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
2461d71ae5a4SJacob Faibussowitsch {
2462674ae819SStefano Zampini   FETIDPMat_ctx mat_ctx;
24633425bc38SStefano Zampini 
24643425bc38SStefano Zampini   PetscFunctionBegin;
2465266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat, MAT_CLASSID, 1);
2466266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_sol, VEC_CLASSID, 2);
2467266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_sol, VEC_CLASSID, 3);
24689566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx));
2469cac4c232SBarry Smith   PetscUseMethod(mat_ctx->pc, "PCBDDCMatFETIDPGetSolution_C", (Mat, Vec, Vec), (fetidp_mat, fetidp_flux_sol, standard_sol));
24703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24713425bc38SStefano Zampini }
24721e6b0712SBarry Smith 
2473d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc)
2474d71ae5a4SJacob Faibussowitsch {
2475674ae819SStefano Zampini   FETIDPMat_ctx fetidpmat_ctx;
24763425bc38SStefano Zampini   Mat           newmat;
2477674ae819SStefano Zampini   FETIDPPC_ctx  fetidppc_ctx;
24783425bc38SStefano Zampini   PC            newpc;
2479ce94432eSBarry Smith   MPI_Comm      comm;
24803425bc38SStefano Zampini 
24813425bc38SStefano Zampini   PetscFunctionBegin;
24829566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)pc, &comm));
248315579a77SStefano Zampini   /* FETI-DP matrix */
24849566063dSJacob Faibussowitsch   PetscCall(PCBDDCCreateFETIDPMatContext(pc, &fetidpmat_ctx));
24851720468bSStefano Zampini   fetidpmat_ctx->fully_redundant = fully_redundant;
24869566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetupFETIDPMatContext(fetidpmat_ctx));
24879566063dSJacob Faibussowitsch   PetscCall(MatCreateShell(comm, fetidpmat_ctx->n, fetidpmat_ctx->n, fetidpmat_ctx->N, fetidpmat_ctx->N, fetidpmat_ctx, &newmat));
24889566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)newmat, !fetidpmat_ctx->l2g_lambda_only ? "F" : "G"));
24899566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(newmat, MATOP_MULT, (void (*)(void))FETIDPMatMult));
24909566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(newmat, MATOP_MULT_TRANSPOSE, (void (*)(void))FETIDPMatMultTranspose));
24919566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(newmat, MATOP_DESTROY, (void (*)(void))PCBDDCDestroyFETIDPMat));
249215579a77SStefano Zampini   /* propagate MatOptions */
249315579a77SStefano Zampini   {
249415579a77SStefano Zampini     PC_BDDC  *pcbddc = (PC_BDDC *)fetidpmat_ctx->pc->data;
2495b94d7dedSBarry Smith     PetscBool isset, issym;
249615579a77SStefano Zampini 
2497b94d7dedSBarry Smith     PetscCall(MatIsSymmetricKnown(pc->mat, &isset, &issym));
2498b94d7dedSBarry Smith     if ((isset && issym) || pcbddc->symmetric_primal) PetscCall(MatSetOption(newmat, MAT_SYMMETRIC, PETSC_TRUE));
249915579a77SStefano Zampini   }
25009566063dSJacob Faibussowitsch   PetscCall(MatSetOptionsPrefix(newmat, prefix));
25019566063dSJacob Faibussowitsch   PetscCall(MatAppendOptionsPrefix(newmat, "fetidp_"));
25029566063dSJacob Faibussowitsch   PetscCall(MatSetUp(newmat));
250315579a77SStefano Zampini   /* FETI-DP preconditioner */
25049566063dSJacob Faibussowitsch   PetscCall(PCBDDCCreateFETIDPPCContext(pc, &fetidppc_ctx));
25059566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetupFETIDPPCContext(newmat, fetidppc_ctx));
25069566063dSJacob Faibussowitsch   PetscCall(PCCreate(comm, &newpc));
25079566063dSJacob Faibussowitsch   PetscCall(PCSetOperators(newpc, newmat, newmat));
25089566063dSJacob Faibussowitsch   PetscCall(PCSetOptionsPrefix(newpc, prefix));
25099566063dSJacob Faibussowitsch   PetscCall(PCAppendOptionsPrefix(newpc, "fetidp_"));
25109566063dSJacob Faibussowitsch   PetscCall(PCSetErrorIfFailure(newpc, pc->erroriffailure));
251115579a77SStefano Zampini   if (!fetidpmat_ctx->l2g_lambda_only) { /* standard FETI-DP */
25129566063dSJacob Faibussowitsch     PetscCall(PCSetType(newpc, PCSHELL));
25139566063dSJacob Faibussowitsch     PetscCall(PCShellSetName(newpc, "FETI-DP multipliers"));
25149566063dSJacob Faibussowitsch     PetscCall(PCShellSetContext(newpc, fetidppc_ctx));
25159566063dSJacob Faibussowitsch     PetscCall(PCShellSetApply(newpc, FETIDPPCApply));
25169566063dSJacob Faibussowitsch     PetscCall(PCShellSetApplyTranspose(newpc, FETIDPPCApplyTranspose));
25179566063dSJacob Faibussowitsch     PetscCall(PCShellSetView(newpc, FETIDPPCView));
25189566063dSJacob Faibussowitsch     PetscCall(PCShellSetDestroy(newpc, PCBDDCDestroyFETIDPPC));
25195a1e936bSStefano Zampini   } else { /* saddle-point FETI-DP */
25205a1e936bSStefano Zampini     Mat       M;
25215a1e936bSStefano Zampini     PetscInt  psize;
25225a1e936bSStefano Zampini     PetscBool fake = PETSC_FALSE, isfieldsplit;
2523e1214c54Sstefano_zampini 
25249566063dSJacob Faibussowitsch     PetscCall(ISViewFromOptions(fetidpmat_ctx->lagrange, NULL, "-lag_view"));
25259566063dSJacob Faibussowitsch     PetscCall(ISViewFromOptions(fetidpmat_ctx->pressure, NULL, "-press_view"));
25269566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_PPmat", (PetscObject *)&M));
25279566063dSJacob Faibussowitsch     PetscCall(PCSetType(newpc, PCFIELDSPLIT));
25289566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetIS(newpc, "lag", fetidpmat_ctx->lagrange));
25299566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetIS(newpc, "p", fetidpmat_ctx->pressure));
25309566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetType(newpc, PC_COMPOSITE_SCHUR));
25319566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetSchurFactType(newpc, PC_FIELDSPLIT_SCHUR_FACT_DIAG));
25329566063dSJacob Faibussowitsch     PetscCall(ISGetSize(fetidpmat_ctx->pressure, &psize));
25335a1e936bSStefano Zampini     if (psize != M->rmap->N) {
25345a1e936bSStefano Zampini       Mat      M2;
25355a1e936bSStefano Zampini       PetscInt lpsize;
25365a1e936bSStefano Zampini 
25375a1e936bSStefano Zampini       fake = PETSC_TRUE;
25389566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(fetidpmat_ctx->pressure, &lpsize));
25399566063dSJacob Faibussowitsch       PetscCall(MatCreate(comm, &M2));
25409566063dSJacob Faibussowitsch       PetscCall(MatSetType(M2, MATAIJ));
25419566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(M2, lpsize, lpsize, psize, psize));
25429566063dSJacob Faibussowitsch       PetscCall(MatSetUp(M2));
25439566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(M2, MAT_FINAL_ASSEMBLY));
25449566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(M2, MAT_FINAL_ASSEMBLY));
25459566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSetSchurPre(newpc, PC_FIELDSPLIT_SCHUR_PRE_USER, M2));
25469566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&M2));
25475a1e936bSStefano Zampini     } else {
25489566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSetSchurPre(newpc, PC_FIELDSPLIT_SCHUR_PRE_USER, M));
25495a1e936bSStefano Zampini     }
25509566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetSchurScale(newpc, 1.0));
255115579a77SStefano Zampini 
255215579a77SStefano Zampini     /* we need to setfromoptions and setup here to access the blocks */
25539566063dSJacob Faibussowitsch     PetscCall(PCSetFromOptions(newpc));
25549566063dSJacob Faibussowitsch     PetscCall(PCSetUp(newpc));
2555e1214c54Sstefano_zampini 
25565a1e936bSStefano Zampini     /* user may have changed the type (e.g. -fetidp_pc_type none) */
25579566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)newpc, PCFIELDSPLIT, &isfieldsplit));
25585a1e936bSStefano Zampini     if (isfieldsplit) {
25595a1e936bSStefano Zampini       KSP      *ksps;
25605a1e936bSStefano Zampini       PC        ppc, lagpc;
25615a1e936bSStefano Zampini       PetscInt  nn;
2562064a4176SStefano Zampini       PetscBool ismatis, matisok = PETSC_FALSE, check = PETSC_FALSE;
25635a1e936bSStefano Zampini 
2564e1214c54Sstefano_zampini       /* set the solver for the (0,0) block */
25659566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSchurGetSubKSP(newpc, &nn, &ksps));
25665a1e936bSStefano Zampini       if (!nn) { /* not of type PC_COMPOSITE_SCHUR */
25679566063dSJacob Faibussowitsch         PetscCall(PCFieldSplitGetSubKSP(newpc, &nn, &ksps));
25685a1e936bSStefano Zampini         if (!fake) { /* pass pmat to the pressure solver */
25695a1e936bSStefano Zampini           Mat F;
25705a1e936bSStefano Zampini 
25719566063dSJacob Faibussowitsch           PetscCall(KSPGetOperators(ksps[1], &F, NULL));
25729566063dSJacob Faibussowitsch           PetscCall(KSPSetOperators(ksps[1], F, M));
25735a1e936bSStefano Zampini         }
25745a1e936bSStefano Zampini       } else {
2575b94d7dedSBarry Smith         PetscBool issym, isset;
25765a1e936bSStefano Zampini         Mat       S;
25775a1e936bSStefano Zampini 
25789566063dSJacob Faibussowitsch         PetscCall(PCFieldSplitSchurGetS(newpc, &S));
2579b94d7dedSBarry Smith         PetscCall(MatIsSymmetricKnown(newmat, &isset, &issym));
2580b94d7dedSBarry Smith         if (isset) PetscCall(MatSetOption(S, MAT_SYMMETRIC, issym));
25815a1e936bSStefano Zampini       }
25829566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksps[0], &lagpc));
25839566063dSJacob Faibussowitsch       PetscCall(PCSetType(lagpc, PCSHELL));
25849566063dSJacob Faibussowitsch       PetscCall(PCShellSetName(lagpc, "FETI-DP multipliers"));
25859566063dSJacob Faibussowitsch       PetscCall(PCShellSetContext(lagpc, fetidppc_ctx));
25869566063dSJacob Faibussowitsch       PetscCall(PCShellSetApply(lagpc, FETIDPPCApply));
25879566063dSJacob Faibussowitsch       PetscCall(PCShellSetApplyTranspose(lagpc, FETIDPPCApplyTranspose));
25889566063dSJacob Faibussowitsch       PetscCall(PCShellSetView(lagpc, FETIDPPCView));
25899566063dSJacob Faibussowitsch       PetscCall(PCShellSetDestroy(lagpc, PCBDDCDestroyFETIDPPC));
25905a1e936bSStefano Zampini 
25915a1e936bSStefano Zampini       /* Olof's idea: interface Schur complement preconditioner for the mass matrix */
25929566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksps[1], &ppc));
25935a1e936bSStefano Zampini       if (fake) {
25945a1e936bSStefano Zampini         BDDCIPC_ctx    bddcipc_ctx;
2595ff11fd76SStefano Zampini         PetscContainer c;
25965a1e936bSStefano Zampini 
25975a1e936bSStefano Zampini         matisok = PETSC_TRUE;
25985a1e936bSStefano Zampini 
25995a1e936bSStefano Zampini         /* create inner BDDC solver */
26009566063dSJacob Faibussowitsch         PetscCall(PetscNew(&bddcipc_ctx));
26019566063dSJacob Faibussowitsch         PetscCall(PCCreate(comm, &bddcipc_ctx->bddc));
26029566063dSJacob Faibussowitsch         PetscCall(PCSetType(bddcipc_ctx->bddc, PCBDDC));
26039566063dSJacob Faibussowitsch         PetscCall(PCSetOperators(bddcipc_ctx->bddc, M, M));
26049566063dSJacob Faibussowitsch         PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_pCSR", (PetscObject *)&c));
26059566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)M, MATIS, &ismatis));
2606ff11fd76SStefano Zampini         if (c && ismatis) {
2607ff11fd76SStefano Zampini           Mat       lM;
2608ff11fd76SStefano Zampini           PetscInt *csr, n;
2609ff11fd76SStefano Zampini 
26109566063dSJacob Faibussowitsch           PetscCall(MatISGetLocalMat(M, &lM));
26119566063dSJacob Faibussowitsch           PetscCall(MatGetSize(lM, &n, NULL));
26129566063dSJacob Faibussowitsch           PetscCall(PetscContainerGetPointer(c, (void **)&csr));
26139566063dSJacob Faibussowitsch           PetscCall(PCBDDCSetLocalAdjacencyGraph(bddcipc_ctx->bddc, n, csr, csr + (n + 1), PETSC_COPY_VALUES));
26149566063dSJacob Faibussowitsch           PetscCall(MatISRestoreLocalMat(M, &lM));
2615ff11fd76SStefano Zampini         }
26169566063dSJacob Faibussowitsch         PetscCall(PCSetOptionsPrefix(bddcipc_ctx->bddc, ((PetscObject)ksps[1])->prefix));
26179566063dSJacob Faibussowitsch         PetscCall(PCSetErrorIfFailure(bddcipc_ctx->bddc, pc->erroriffailure));
26189566063dSJacob Faibussowitsch         PetscCall(PCSetFromOptions(bddcipc_ctx->bddc));
26195a1e936bSStefano Zampini 
26205a1e936bSStefano Zampini         /* wrap the interface application */
26219566063dSJacob Faibussowitsch         PetscCall(PCSetType(ppc, PCSHELL));
26229566063dSJacob Faibussowitsch         PetscCall(PCShellSetName(ppc, "FETI-DP pressure"));
26239566063dSJacob Faibussowitsch         PetscCall(PCShellSetContext(ppc, bddcipc_ctx));
26249566063dSJacob Faibussowitsch         PetscCall(PCShellSetSetUp(ppc, PCSetUp_BDDCIPC));
26259566063dSJacob Faibussowitsch         PetscCall(PCShellSetApply(ppc, PCApply_BDDCIPC));
26269566063dSJacob Faibussowitsch         PetscCall(PCShellSetApplyTranspose(ppc, PCApplyTranspose_BDDCIPC));
26279566063dSJacob Faibussowitsch         PetscCall(PCShellSetView(ppc, PCView_BDDCIPC));
26289566063dSJacob Faibussowitsch         PetscCall(PCShellSetDestroy(ppc, PCDestroy_BDDCIPC));
26295a1e936bSStefano Zampini       }
26305a1e936bSStefano Zampini 
26315a1e936bSStefano Zampini       /* determine if we need to assemble M to construct a preconditioner */
26325a1e936bSStefano Zampini       if (!matisok) {
26339566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)M, MATIS, &ismatis));
26349566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompareAny((PetscObject)ppc, &matisok, PCBDDC, PCJACOBI, PCNONE, PCMG, ""));
263548a46eb9SPierre Jolivet         if (ismatis && !matisok) PetscCall(MatConvert(M, MATAIJ, MAT_INPLACE_MATRIX, &M));
26365a1e936bSStefano Zampini       }
2637064a4176SStefano Zampini 
2638064a4176SStefano Zampini       /* run the subproblems to check convergence */
26399566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)newmat)->prefix, "-check_saddlepoint", &check, NULL));
2640064a4176SStefano Zampini       if (check) {
2641064a4176SStefano Zampini         PetscInt i;
2642064a4176SStefano Zampini 
2643064a4176SStefano Zampini         for (i = 0; i < nn; i++) {
2644064a4176SStefano Zampini           KSP       kspC;
2645e8f11ae9SBarry Smith           PC        npc;
2646064a4176SStefano Zampini           Mat       F, pF;
2647064a4176SStefano Zampini           Vec       x, y;
2648064a4176SStefano Zampini           PetscBool isschur, prec = PETSC_TRUE;
2649064a4176SStefano Zampini 
26509566063dSJacob Faibussowitsch           PetscCall(KSPCreate(PetscObjectComm((PetscObject)ksps[i]), &kspC));
26513821be0aSBarry Smith           PetscCall(KSPSetNestLevel(kspC, pc->kspnestlevel));
26529566063dSJacob Faibussowitsch           PetscCall(KSPSetOptionsPrefix(kspC, ((PetscObject)ksps[i])->prefix));
26539566063dSJacob Faibussowitsch           PetscCall(KSPAppendOptionsPrefix(kspC, "check_"));
26549566063dSJacob Faibussowitsch           PetscCall(KSPGetOperators(ksps[i], &F, &pF));
26559566063dSJacob Faibussowitsch           PetscCall(PetscObjectTypeCompare((PetscObject)F, MATSCHURCOMPLEMENT, &isschur));
2656064a4176SStefano Zampini           if (isschur) {
2657064a4176SStefano Zampini             KSP  kspS, kspS2;
2658064a4176SStefano Zampini             Mat  A00, pA00, A10, A01, A11;
2659064a4176SStefano Zampini             char prefix[256];
2660064a4176SStefano Zampini 
26619566063dSJacob Faibussowitsch             PetscCall(MatSchurComplementGetKSP(F, &kspS));
26629566063dSJacob Faibussowitsch             PetscCall(MatSchurComplementGetSubMatrices(F, &A00, &pA00, &A01, &A10, &A11));
26639566063dSJacob Faibussowitsch             PetscCall(MatCreateSchurComplement(A00, pA00, A01, A10, A11, &F));
26649566063dSJacob Faibussowitsch             PetscCall(MatSchurComplementGetKSP(F, &kspS2));
26659566063dSJacob Faibussowitsch             PetscCall(PetscSNPrintf(prefix, sizeof(prefix), "%sschur_", ((PetscObject)kspC)->prefix));
26669566063dSJacob Faibussowitsch             PetscCall(KSPSetOptionsPrefix(kspS2, prefix));
2667e8f11ae9SBarry Smith             PetscCall(KSPGetPC(kspS2, &npc));
2668e8f11ae9SBarry Smith             PetscCall(PCSetType(npc, PCKSP));
2669e8f11ae9SBarry Smith             PetscCall(PCKSPSetKSP(npc, kspS));
26709566063dSJacob Faibussowitsch             PetscCall(KSPSetFromOptions(kspS2));
2671e8f11ae9SBarry Smith             PetscCall(KSPGetPC(kspS2, &npc));
2672e8f11ae9SBarry Smith             PetscCall(PCSetUseAmat(npc, PETSC_TRUE));
2673064a4176SStefano Zampini           } else {
26749566063dSJacob Faibussowitsch             PetscCall(PetscObjectReference((PetscObject)F));
2675064a4176SStefano Zampini           }
26769566063dSJacob Faibussowitsch           PetscCall(KSPSetFromOptions(kspC));
26779566063dSJacob Faibussowitsch           PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)kspC)->prefix, "-preconditioned", &prec, NULL));
2678064a4176SStefano Zampini           if (prec) {
2679e8f11ae9SBarry Smith             PetscCall(KSPGetPC(ksps[i], &npc));
2680e8f11ae9SBarry Smith             PetscCall(KSPSetPC(kspC, npc));
2681064a4176SStefano Zampini           }
26829566063dSJacob Faibussowitsch           PetscCall(KSPSetOperators(kspC, F, pF));
26839566063dSJacob Faibussowitsch           PetscCall(MatCreateVecs(F, &x, &y));
26849566063dSJacob Faibussowitsch           PetscCall(VecSetRandom(x, NULL));
26859566063dSJacob Faibussowitsch           PetscCall(MatMult(F, x, y));
26869566063dSJacob Faibussowitsch           PetscCall(KSPSolve(kspC, y, x));
2687e8f11ae9SBarry Smith           PetscCall(KSPCheckSolve(kspC, npc, x));
26889566063dSJacob Faibussowitsch           PetscCall(KSPDestroy(&kspC));
26899566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&F));
26909566063dSJacob Faibussowitsch           PetscCall(VecDestroy(&x));
26919566063dSJacob Faibussowitsch           PetscCall(VecDestroy(&y));
2692064a4176SStefano Zampini         }
2693064a4176SStefano Zampini       }
26949566063dSJacob Faibussowitsch       PetscCall(PetscFree(ksps));
2695e1214c54Sstefano_zampini     }
26965a1e936bSStefano Zampini   }
26973425bc38SStefano Zampini   /* return pointers for objects created */
26983425bc38SStefano Zampini   *fetidp_mat = newmat;
26993425bc38SStefano Zampini   *fetidp_pc  = newpc;
27003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27013425bc38SStefano Zampini }
27021e6b0712SBarry Smith 
270394ef8ddeSSatish Balay /*@C
27040f202f7eSStefano Zampini   PCBDDCCreateFETIDPOperators - Create FETI-DP operators
27053425bc38SStefano Zampini 
27063425bc38SStefano Zampini   Collective
27073425bc38SStefano Zampini 
27083425bc38SStefano Zampini   Input Parameters:
270998ad52f2SBarry Smith + pc              - the `PCBDDC` preconditioning context (setup should have been called before)
2710547c9a8eSstefano_zampini . fully_redundant - true for a fully redundant set of Lagrange multipliers
271120f4b53cSBarry Smith - prefix          - optional options database prefix for the objects to be created (can be `NULL`)
271228509bceSStefano Zampini 
271328509bceSStefano Zampini   Output Parameters:
27140f202f7eSStefano Zampini + fetidp_mat - shell FETI-DP matrix object
27150f202f7eSStefano Zampini - fetidp_pc  - shell Dirichlet preconditioner for FETI-DP matrix
271628509bceSStefano Zampini 
27173425bc38SStefano Zampini   Level: developer
27183425bc38SStefano Zampini 
2719f1580f4eSBarry Smith   Note:
2720f1580f4eSBarry Smith   Currently the only operations provided for FETI-DP matrix are `MatMult()` and `MatMultTranspose()`
27213425bc38SStefano Zampini 
2722562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCMatFETIDPGetRHS()`, `PCBDDCMatFETIDPGetSolution()`
27233425bc38SStefano Zampini @*/
2724d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc)
2725d71ae5a4SJacob Faibussowitsch {
27263425bc38SStefano Zampini   PetscFunctionBegin;
27273425bc38SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
27280fdf79fbSJacob Faibussowitsch   PetscCheck(pc->setupcalled, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "You must call PCSetup_BDDC() first");
2729cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCCreateFETIDPOperators_C", (PC, PetscBool, const char *, Mat *, PC *), (pc, fully_redundant, prefix, fetidp_mat, fetidp_pc));
27303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27313425bc38SStefano Zampini }
2732f1580f4eSBarry Smith 
2733da1bb401SStefano Zampini /*MC
27341d27aa22SBarry Smith    PCBDDC - Balancing Domain Decomposition by Constraints preconditioners, {cite}`dohrmann2007approximate`, {cite}`klawonn2006dual`, {cite}`mandel2008multispace`
27350c7d97c5SJed Brown 
2736f1580f4eSBarry Smith    Requires `MATIS` matrices (Pmat) with local matrices (inside the `MATIS`) of type `MATSEQAIJ`, `MATSEQBAIJ` or `MATSEQSBAIJ`
273728509bceSStefano Zampini 
273828509bceSStefano Zampini    It also works with unsymmetric and indefinite problems.
273928509bceSStefano Zampini 
2740f1580f4eSBarry Smith    Unlike 'conventional' interface preconditioners, `PCBDDC` iterates over all degrees of freedom, not just those on the interface. This allows the use
2741f1580f4eSBarry Smith    of approximate solvers on the subdomains.
2742b6fdb6dfSStefano Zampini 
27431d27aa22SBarry Smith    Approximate local solvers are automatically adapted (see {cite}`dohrmann2007approximate`,) if the user has attached a nullspace object to the subdomain matrices, and informed
2744f1580f4eSBarry Smith    `PCBDDC` of using approximate solvers (via the command line).
274528509bceSStefano Zampini 
2746f1580f4eSBarry 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.
2747f1580f4eSBarry Smith    The latter can be customized by using `PCBDDCSetLocalAdjacencyGraph()`
274828509bceSStefano Zampini 
2749f1580f4eSBarry Smith    Additional information on dofs can be provided by using `PCBDDCSetDofsSplitting()`, `PCBDDCSetDirichletBoundaries()`, `PCBDDCSetNeumannBoundaries()`, and
2750f1580f4eSBarry Smith    `PCBDDCSetPrimalVerticesIS()` and their local counterparts.
275128509bceSStefano Zampini 
2752f1580f4eSBarry Smith    Constraints can be customized by attaching a `MatNullSpace` object to the `MATIS` matrix via `MatSetNearNullSpace()`. Non-singular modes are retained via SVD.
275328509bceSStefano Zampini 
27541d27aa22SBarry Smith    Change of basis is performed similarly to {cite}`klawonn2006dual` when requested. When more than one constraint is present on a single connected component
2755f1580f4eSBarry Smith    (i.e. an edge or a face), a robust method based on local QR factorizations is used.
2756f1580f4eSBarry Smith    User defined change of basis can be passed to `PCBDDC` with `PCBDDCSetChangeOfBasisMat()`
275728509bceSStefano Zampini 
27581d27aa22SBarry Smith    The PETSc implementation also supports multilevel `PCBDDC` {cite}`mandel2008multispace`. Coarse grids are partitioned using a `MatPartitioning` object.
275928509bceSStefano Zampini 
27601d27aa22SBarry Smith    Adaptive selection of primal constraints is supported for SPD systems with high-contrast in the coefficients if MUMPS or MKL_PARDISO are present.
2761f1580f4eSBarry Smith    Future versions of the code will also consider using PASTIX.
27620f202f7eSStefano Zampini 
2763f1580f4eSBarry Smith    An experimental interface to the FETI-DP method is available. FETI-DP operators could be created using `PCBDDCCreateFETIDPOperators()`.
2764f1580f4eSBarry Smith     A stand-alone class for the FETI-DP method will be provided in the next releases.
27650f202f7eSStefano Zampini 
2766f1580f4eSBarry Smith    Options Database Keys:
2767a2b725a8SWilliam Gropp +    -pc_bddc_use_vertices <true>         - use or not vertices in primal space
27680f202f7eSStefano Zampini .    -pc_bddc_use_edges <true>            - use or not edges in primal space
27690f202f7eSStefano Zampini .    -pc_bddc_use_faces <false>           - use or not faces in primal space
27700f202f7eSStefano Zampini .    -pc_bddc_symmetric <true>            - symmetric computation of primal basis functions. Specify false for unsymmetric problems
27710f202f7eSStefano Zampini .    -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only)
27720f202f7eSStefano Zampini .    -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested
27730f202f7eSStefano Zampini .    -pc_bddc_switch_static <false>       - switches from M_2 (default) to M_3 operator (see reference article [1])
277428509bceSStefano Zampini .    -pc_bddc_levels <0>                  - maximum number of levels for multilevel
27750f202f7eSStefano 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)
27765459c157SBarry 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)
27770f202f7eSStefano Zampini .    -pc_bddc_use_deluxe_scaling <false>  - use deluxe scaling
277871f2caa7Sprj- .    -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)
2779bd2a564bSStefano 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)
278028509bceSStefano Zampini -    -pc_bddc_check_level <0>             - set verbosity level of debugging output
278128509bceSStefano Zampini 
2782f1580f4eSBarry Smith    Options for Dirichlet, Neumann or coarse solver can be set using the appropriate options prefix
278328509bceSStefano Zampini .vb
278428509bceSStefano Zampini       -pc_bddc_dirichlet_
278528509bceSStefano Zampini       -pc_bddc_neumann_
278628509bceSStefano Zampini       -pc_bddc_coarse_
278728509bceSStefano Zampini .ve
2788f1580f4eSBarry Smith    e.g. -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. `PCBDDC` uses by default `KSPPREONLY` and `PCLU`.
278928509bceSStefano Zampini 
2790f1580f4eSBarry Smith    When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified using the options prefix
279128509bceSStefano Zampini .vb
2792312be037SStefano Zampini       -pc_bddc_dirichlet_lN_
2793312be037SStefano Zampini       -pc_bddc_neumann_lN_
2794312be037SStefano Zampini       -pc_bddc_coarse_lN_
279528509bceSStefano Zampini .ve
27960f202f7eSStefano Zampini    Note that level number ranges from the finest (0) to the coarsest (N).
2797f1580f4eSBarry 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
2798f1580f4eSBarry Smith    to the option, e.g.
27990f202f7eSStefano Zampini .vb
28000f202f7eSStefano Zampini      -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3
28010f202f7eSStefano Zampini .ve
28020f202f7eSStefano 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
2803da1bb401SStefano Zampini 
2804da1bb401SStefano Zampini    Level: intermediate
2805da1bb401SStefano Zampini 
28061d27aa22SBarry Smith    Contributed by:
28071d27aa22SBarry Smith    Stefano Zampini
2808da1bb401SStefano Zampini 
2809562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `MATIS`, `PCLU`, `PCGAMG`, `PC`, `PCBDDCSetLocalAdjacencyGraph()`, `PCBDDCSetDofsSplitting()`,
2810f1580f4eSBarry Smith           `PCBDDCSetDirichletBoundaries()`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCSetPrimalVerticesIS()`, `MatNullSpace`, `MatSetNearNullSpace()`,
2811f1580f4eSBarry Smith           `PCBDDCSetChangeOfBasisMat()`, `PCBDDCCreateFETIDPOperators()`, `PCNN`
2812da1bb401SStefano Zampini M*/
2813b2573a8aSBarry Smith 
2814d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
2815d71ae5a4SJacob Faibussowitsch {
2816da1bb401SStefano Zampini   PC_BDDC *pcbddc;
2817da1bb401SStefano Zampini 
2818da1bb401SStefano Zampini   PetscFunctionBegin;
28194dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&pcbddc));
28203ec1f749SStefano Zampini   pc->data = pcbddc;
2821da1bb401SStefano Zampini 
282204c3f3b8SBarry Smith   PetscCall(PCISInitialize(pc));
2823da1bb401SStefano Zampini 
28249326c5c6Sstefano_zampini   /* create local graph structure */
28259566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphCreate(&pcbddc->mat_graph));
28269326c5c6Sstefano_zampini 
28279326c5c6Sstefano_zampini   /* BDDC nonzero defaults */
28286d9e27e4SStefano Zampini   pcbddc->use_nnsp                  = PETSC_TRUE;
282908a5cf49SStefano Zampini   pcbddc->use_local_adj             = PETSC_TRUE;
283047d04d0dSStefano Zampini   pcbddc->use_vertices              = PETSC_TRUE;
283147d04d0dSStefano Zampini   pcbddc->use_edges                 = PETSC_TRUE;
28323301b35fSStefano Zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
283314f95afaSStefano Zampini   pcbddc->vertex_size               = 1;
2834c703fcc7SStefano Zampini   pcbddc->recompute_topography      = PETSC_TRUE;
283568457ee5SStefano Zampini   pcbddc->coarse_size               = -1;
283685c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
283747d04d0dSStefano Zampini   pcbddc->coarsening_ratio          = 8;
283857de7509SStefano Zampini   pcbddc->coarse_eqs_per_proc       = 1;
283927b6a85dSStefano Zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
28401e0482f5SStefano Zampini   pcbddc->nedfield                  = -1;
28411e0482f5SStefano Zampini   pcbddc->nedglobal                 = PETSC_TRUE;
2842be12c134Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
2843b96c3477SStefano Zampini   pcbddc->sub_schurs_layers         = -1;
2844bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[0]     = 0.0;
2845bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[1]     = 0.0;
2846b7eb3628SStefano Zampini 
2847da1bb401SStefano Zampini   /* function pointers */
2848da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
284993bd9ae7SStefano Zampini   pc->ops->applytranspose      = PCApplyTranspose_BDDC;
2850da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
2851da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
2852da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
28536b78500eSPatrick Sanan   pc->ops->view                = PCView_BDDC;
28540a545947SLisandro Dalcin   pc->ops->applyrichardson     = NULL;
28550a545947SLisandro Dalcin   pc->ops->applysymmetricleft  = NULL;
28560a545947SLisandro Dalcin   pc->ops->applysymmetricright = NULL;
2857534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
2858534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
28599326c5c6Sstefano_zampini   pc->ops->reset               = PCReset_BDDC;
2860da1bb401SStefano Zampini 
2861da1bb401SStefano Zampini   /* composing function */
28629566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDiscreteGradient_C", PCBDDCSetDiscreteGradient_BDDC));
28639566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDivergenceMat_C", PCBDDCSetDivergenceMat_BDDC));
28649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetChangeOfBasisMat_C", PCBDDCSetChangeOfBasisMat_BDDC));
28659566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesLocalIS_C", PCBDDCSetPrimalVerticesLocalIS_BDDC));
28669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesIS_C", PCBDDCSetPrimalVerticesIS_BDDC));
28679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesLocalIS_C", PCBDDCGetPrimalVerticesLocalIS_BDDC));
28689566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesIS_C", PCBDDCGetPrimalVerticesIS_BDDC));
28699566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetCoarseningRatio_C", PCBDDCSetCoarseningRatio_BDDC));
28709566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevel_C", PCBDDCSetLevel_BDDC));
28719566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetUseExactDirichlet_C", PCBDDCSetUseExactDirichlet_BDDC));
28729566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevels_C", PCBDDCSetLevels_BDDC));
28739566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundaries_C", PCBDDCSetDirichletBoundaries_BDDC));
28749566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundariesLocal_C", PCBDDCSetDirichletBoundariesLocal_BDDC));
28759566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundaries_C", PCBDDCSetNeumannBoundaries_BDDC));
28769566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundariesLocal_C", PCBDDCSetNeumannBoundariesLocal_BDDC));
28779566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundaries_C", PCBDDCGetDirichletBoundaries_BDDC));
28789566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundariesLocal_C", PCBDDCGetDirichletBoundariesLocal_BDDC));
28799566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundaries_C", PCBDDCGetNeumannBoundaries_BDDC));
28809566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundariesLocal_C", PCBDDCGetNeumannBoundariesLocal_BDDC));
28819566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplitting_C", PCBDDCSetDofsSplitting_BDDC));
28829566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplittingLocal_C", PCBDDCSetDofsSplittingLocal_BDDC));
28839566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", PCBDDCSetLocalAdjacencyGraph_BDDC));
28849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCCreateFETIDPOperators_C", PCBDDCCreateFETIDPOperators_BDDC));
28859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetRHS_C", PCBDDCMatFETIDPGetRHS_BDDC));
28869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetSolution_C", PCBDDCMatFETIDPGetSolution_BDDC));
28879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", PCPreSolveChangeRHS_BDDC));
28889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_BDDC));
28893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2890da1bb401SStefano Zampini }
289143371fb9SStefano Zampini 
289243371fb9SStefano Zampini /*@C
2893f1580f4eSBarry Smith   PCBDDCInitializePackage - This function initializes everything in the `PCBDDC` package. It is called
2894f1580f4eSBarry Smith   from `PCInitializePackage()`.
289543371fb9SStefano Zampini 
289643371fb9SStefano Zampini   Level: developer
289743371fb9SStefano Zampini 
2898562efe2eSBarry Smith .seealso: [](ch_ksp), `PetscInitialize()`, `PCBDDCFinalizePackage()`
289943371fb9SStefano Zampini @*/
2900d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCInitializePackage(void)
2901d71ae5a4SJacob Faibussowitsch {
290243371fb9SStefano Zampini   int i;
290343371fb9SStefano Zampini 
290443371fb9SStefano Zampini   PetscFunctionBegin;
29053ba16761SJacob Faibussowitsch   if (PCBDDCPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS);
290643371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_TRUE;
29079566063dSJacob Faibussowitsch   PetscCall(PetscRegisterFinalize(PCBDDCFinalizePackage));
290843371fb9SStefano Zampini 
290943371fb9SStefano Zampini   /* general events */
29109566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCTopo", PC_CLASSID, &PC_BDDC_Topology[0]));
29119566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCLKSP", PC_CLASSID, &PC_BDDC_LocalSolvers[0]));
29129566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCLWor", PC_CLASSID, &PC_BDDC_LocalWork[0]));
29139566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCorr", PC_CLASSID, &PC_BDDC_CorrectionSetUp[0]));
29149566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCASet", PC_CLASSID, &PC_BDDC_ApproxSetUp[0]));
29159566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCAApp", PC_CLASSID, &PC_BDDC_ApproxApply[0]));
29169566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCSet", PC_CLASSID, &PC_BDDC_CoarseSetUp[0]));
29179566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCKSP", PC_CLASSID, &PC_BDDC_CoarseSolver[0]));
29189566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCAdap", PC_CLASSID, &PC_BDDC_AdaptiveSetUp[0]));
29199566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCScal", PC_CLASSID, &PC_BDDC_Scaling[0]));
29209566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCSchr", PC_CLASSID, &PC_BDDC_Schurs[0]));
29219566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCDirS", PC_CLASSID, &PC_BDDC_Solves[0][0]));
29229566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCNeuS", PC_CLASSID, &PC_BDDC_Solves[0][1]));
29239566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCoaS", PC_CLASSID, &PC_BDDC_Solves[0][2]));
292443371fb9SStefano Zampini   for (i = 1; i < PETSC_PCBDDC_MAXLEVELS; i++) {
292543371fb9SStefano Zampini     char ename[32];
292643371fb9SStefano Zampini 
29279566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCTopo l%02d", i));
29289566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Topology[i]));
29299566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCLKSP l%02d", i));
29309566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_LocalSolvers[i]));
29319566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCLWor l%02d", i));
29329566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_LocalWork[i]));
29339566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCorr l%02d", i));
29349566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CorrectionSetUp[i]));
29359566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCASet l%02d", i));
29369566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_ApproxSetUp[i]));
29379566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCAApp l%02d", i));
29389566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_ApproxApply[i]));
29399566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCSet l%02d", i));
29409566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CoarseSetUp[i]));
29419566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCKSP l%02d", i));
29429566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CoarseSolver[i]));
29439566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCAdap l%02d", i));
29449566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_AdaptiveSetUp[i]));
29459566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCScal l%02d", i));
29469566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Scaling[i]));
29479566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCSchr l%02d", i));
29489566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Schurs[i]));
29499566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCDirS l%02d", i));
29509566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][0]));
29519566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCNeuS l%02d", i));
29529566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][1]));
29539566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCoaS l%02d", i));
29549566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][2]));
295543371fb9SStefano Zampini   }
29563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
295743371fb9SStefano Zampini }
295843371fb9SStefano Zampini 
295943371fb9SStefano Zampini /*@C
2960f1580f4eSBarry Smith   PCBDDCFinalizePackage - This function frees everything from the `PCBDDC` package. It is
2961f1580f4eSBarry Smith   called from `PetscFinalize()` automatically.
296243371fb9SStefano Zampini 
296343371fb9SStefano Zampini   Level: developer
296443371fb9SStefano Zampini 
2965562efe2eSBarry Smith .seealso: [](ch_ksp), `PetscFinalize()`, `PCBDDCInitializePackage()`
296643371fb9SStefano Zampini @*/
2967d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCFinalizePackage(void)
2968d71ae5a4SJacob Faibussowitsch {
296943371fb9SStefano Zampini   PetscFunctionBegin;
297043371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_FALSE;
29713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
297243371fb9SStefano Zampini }
2973