xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision feefa0e191a340680bb02e1467a36facdcb0b150)
153cdbc3dSStefano Zampini /* TODOLIST
2eb97c9d2SStefano Zampini 
3eb97c9d2SStefano Zampini    Solvers
4a0d3c3abSStefano Zampini    - Add support for cholesky for coarse solver (similar to local solvers)
5eb97c9d2SStefano Zampini    - Propagate ksp prefixes for solvers to mat objects?
6eb97c9d2SStefano Zampini 
7eb97c9d2SStefano Zampini    User interface
80f202f7eSStefano Zampini    - ** DM attached to pc?
9eb97c9d2SStefano Zampini 
10eb97c9d2SStefano Zampini    Debugging output
11b9b85e73SStefano Zampini    - * Better management of verbosity levels of debugging output
12eb97c9d2SStefano Zampini 
13eb97c9d2SStefano Zampini    Extra
14b9b85e73SStefano Zampini    - *** Is it possible to work with PCBDDCGraph on boundary indices only (less memory consumed)?
15eb97c9d2SStefano Zampini    - BDDC with MG framework?
16eb97c9d2SStefano Zampini 
17eb97c9d2SStefano Zampini    MATIS related operations contained in BDDC code
18eb97c9d2SStefano Zampini    - Provide general case for subassembling
19eb97c9d2SStefano Zampini 
2053cdbc3dSStefano Zampini */
210c7d97c5SJed Brown 
225e5bbd0aSStefano Zampini #include <petsc/private/pcbddcimpl.h> /*I "petscpc.h" I*/ /* includes for fortran wrappers */
235e5bbd0aSStefano Zampini #include <petsc/private/pcbddcprivateimpl.h>
243b03a366Sstefano_zampini #include <petscblaslapack.h>
25674ae819SStefano Zampini 
2643371fb9SStefano Zampini static PetscBool PCBDDCPackageInitialized = PETSC_FALSE;
2743371fb9SStefano Zampini 
28f3d41395Sstefano_zampini static PetscBool  cited      = PETSC_FALSE;
299371c9d4SSatish Balay static const char citation[] = "@article{ZampiniPCBDDC,\n"
30f3d41395Sstefano_zampini                                "author = {Stefano Zampini},\n"
31f3d41395Sstefano_zampini                                "title = {{PCBDDC}: A Class of Robust Dual-Primal Methods in {PETS}c},\n"
32f3d41395Sstefano_zampini                                "journal = {SIAM Journal on Scientific Computing},\n"
33f3d41395Sstefano_zampini                                "volume = {38},\n"
34f3d41395Sstefano_zampini                                "number = {5},\n"
35f3d41395Sstefano_zampini                                "pages = {S282-S306},\n"
36f3d41395Sstefano_zampini                                "year = {2016},\n"
37f3d41395Sstefano_zampini                                "doi = {10.1137/15M1025785},\n"
38f3d41395Sstefano_zampini                                "URL = {http://dx.doi.org/10.1137/15M1025785},\n"
39f3d41395Sstefano_zampini                                "eprint = {http://dx.doi.org/10.1137/15M1025785}\n"
40f3d41395Sstefano_zampini                                "}\n";
41f3d41395Sstefano_zampini 
4243371fb9SStefano Zampini PetscLogEvent PC_BDDC_Topology[PETSC_PCBDDC_MAXLEVELS];
4343371fb9SStefano Zampini PetscLogEvent PC_BDDC_LocalSolvers[PETSC_PCBDDC_MAXLEVELS];
4443371fb9SStefano Zampini PetscLogEvent PC_BDDC_LocalWork[PETSC_PCBDDC_MAXLEVELS];
4543371fb9SStefano Zampini PetscLogEvent PC_BDDC_CorrectionSetUp[PETSC_PCBDDC_MAXLEVELS];
468ead10e4SStefano Zampini PetscLogEvent PC_BDDC_ApproxSetUp[PETSC_PCBDDC_MAXLEVELS];
478ead10e4SStefano Zampini PetscLogEvent PC_BDDC_ApproxApply[PETSC_PCBDDC_MAXLEVELS];
4843371fb9SStefano Zampini PetscLogEvent PC_BDDC_CoarseSetUp[PETSC_PCBDDC_MAXLEVELS];
4943371fb9SStefano Zampini PetscLogEvent PC_BDDC_CoarseSolver[PETSC_PCBDDC_MAXLEVELS];
5043371fb9SStefano Zampini PetscLogEvent PC_BDDC_AdaptiveSetUp[PETSC_PCBDDC_MAXLEVELS];
5143371fb9SStefano Zampini PetscLogEvent PC_BDDC_Scaling[PETSC_PCBDDC_MAXLEVELS];
5243371fb9SStefano Zampini PetscLogEvent PC_BDDC_Schurs[PETSC_PCBDDC_MAXLEVELS];
5355c176c0SStefano Zampini PetscLogEvent PC_BDDC_Solves[PETSC_PCBDDC_MAXLEVELS][3];
5443371fb9SStefano Zampini 
55bc960bbfSJed Brown const char *const PCBDDCInterfaceExtTypes[] = {"DIRICHLET", "LUMP", "PCBDDCInterfaceExtType", "PC_BDDC_INTERFACE_EXT_", NULL};
56bc960bbfSJed Brown 
570369aaf7SStefano Zampini PetscErrorCode PCApply_BDDC(PC, Vec, Vec);
580369aaf7SStefano Zampini 
59d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetFromOptions_BDDC(PC pc, PetscOptionItems *PetscOptionsObject)
60d71ae5a4SJacob Faibussowitsch {
610c7d97c5SJed Brown   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
62e569e4e1SStefano Zampini   PetscInt nt, i;
630c7d97c5SJed Brown 
640c7d97c5SJed Brown   PetscFunctionBegin;
65d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "BDDC options");
668eeda7d8SStefano Zampini   /* Verbose debugging */
679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_check_level", "Verbose output for PCBDDC (intended for debug)", "none", pcbddc->dbg_flag, &pcbddc->dbg_flag, NULL));
68a13144ffSStefano Zampini   /* Approximate solvers */
699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-pc_bddc_interface_ext_type", "Use DIRICHLET or LUMP to extend interface corrections to interior", "PCBDDCSetInterfaceExtType", PCBDDCInterfaceExtTypes, (PetscEnum)pcbddc->interface_extension, (PetscEnum *)&pcbddc->interface_extension, NULL));
70bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET) {
719566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-pc_bddc_dirichlet_approximate", "Inform PCBDDC that we are using approximate Dirichlet solvers", "none", pcbddc->NullSpace_corr[0], &pcbddc->NullSpace_corr[0], NULL));
729566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-pc_bddc_dirichlet_approximate_scale", "Inform PCBDDC that we need to scale the Dirichlet solve", "none", pcbddc->NullSpace_corr[1], &pcbddc->NullSpace_corr[1], NULL));
73bc960bbfSJed Brown   } else {
74bc960bbfSJed Brown     /* This flag is needed/implied by lumping */
75bc960bbfSJed Brown     pcbddc->switch_static = PETSC_TRUE;
76bc960bbfSJed Brown   }
779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_neumann_approximate", "Inform PCBDDC that we are using approximate Neumann solvers", "none", pcbddc->NullSpace_corr[2], &pcbddc->NullSpace_corr[2], NULL));
789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_neumann_approximate_scale", "Inform PCBDDC that we need to scale the Neumann solve", "none", pcbddc->NullSpace_corr[3], &pcbddc->NullSpace_corr[3], NULL));
796b78500eSPatrick Sanan   /* Primal space customization */
809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_local_mat_graph", "Use or not adjacency graph of local mat for interface analysis", "none", pcbddc->use_local_adj, &pcbddc->use_local_adj, NULL));
819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_graph_maxcount", "Maximum number of shared subdomains for a connected component", "none", pcbddc->graphmaxcount, &pcbddc->graphmaxcount, NULL));
829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_corner_selection", "Activates face-based corner selection", "none", pcbddc->corner_selection, &pcbddc->corner_selection, NULL));
839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_vertices", "Use or not corner dofs in coarse space", "none", pcbddc->use_vertices, &pcbddc->use_vertices, NULL));
849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_edges", "Use or not edge constraints in coarse space", "none", pcbddc->use_edges, &pcbddc->use_edges, NULL));
859566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_faces", "Use or not face constraints in coarse space", "none", pcbddc->use_faces, &pcbddc->use_faces, NULL));
869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_vertex_size", "Connected components smaller or equal to vertex size will be considered as primal vertices", "none", pcbddc->vertex_size, &pcbddc->vertex_size, NULL));
879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_nnsp", "Use near null space attached to the matrix to compute constraints", "none", pcbddc->use_nnsp, &pcbddc->use_nnsp, NULL));
889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_nnsp_true", "Use near null space attached to the matrix to compute constraints as is", "none", pcbddc->use_nnsp_true, &pcbddc->use_nnsp_true, NULL));
899566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_qr_single", "Use QR factorization for single constraints on cc (QR is always used when multiple constraints are present)", "none", pcbddc->use_qr_single, &pcbddc->use_qr_single, NULL));
908eeda7d8SStefano Zampini   /* Change of basis */
919566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_change_of_basis", "Use or not internal change of basis on local edge nodes", "none", pcbddc->use_change_of_basis, &pcbddc->use_change_of_basis, NULL));
929566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_change_on_faces", "Use or not internal change of basis on local face nodes", "none", pcbddc->use_change_on_faces, &pcbddc->use_change_on_faces, NULL));
93ad540459SPierre Jolivet   if (!pcbddc->use_change_of_basis) pcbddc->use_change_on_faces = PETSC_FALSE;
948eeda7d8SStefano Zampini   /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */
959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_switch_static", "Switch on static condensation ops around the interface preconditioner", "none", pcbddc->switch_static, &pcbddc->switch_static, NULL));
969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_coarse_eqs_per_proc", "Target number of equations per process for coarse problem redistribution (significant only at the coarsest level)", "none", pcbddc->coarse_eqs_per_proc, &pcbddc->coarse_eqs_per_proc, NULL));
97e569e4e1SStefano Zampini   i = pcbddc->coarsening_ratio;
989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_coarsening_ratio", "Set coarsening ratio used in multilevel coarsening", "PCBDDCSetCoarseningRatio", i, &i, NULL));
999566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetCoarseningRatio(pc, i));
100e569e4e1SStefano Zampini   i = pcbddc->max_levels;
1019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_levels", "Set maximum number of levels for multilevel", "PCBDDCSetLevels", i, &i, NULL));
1029566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetLevels(pc, i));
1039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_coarse_eqs_limit", "Set maximum number of equations on coarsest grid to aim for", "none", pcbddc->coarse_eqs_limit, &pcbddc->coarse_eqs_limit, NULL));
1049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_coarse_estimates", "Use estimated eigenvalues for coarse problem", "none", pcbddc->use_coarse_estimates, &pcbddc->use_coarse_estimates, NULL));
1059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_deluxe_scaling", "Use deluxe scaling for BDDC", "none", pcbddc->use_deluxe_scaling, &pcbddc->use_deluxe_scaling, NULL));
1069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_schur_rebuild", "Whether or not the interface graph for Schur principal minors has to be rebuilt (i.e. define the interface without any adjacency)", "none", pcbddc->sub_schurs_rebuild, &pcbddc->sub_schurs_rebuild, NULL));
1079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_schur_layers", "Number of dofs' layers for the computation of principal minors (i.e. -1 uses all dofs)", "none", pcbddc->sub_schurs_layers, &pcbddc->sub_schurs_layers, NULL));
1089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_schur_use_useradj", "Whether or not the CSR graph specified by the user should be used for computing successive layers (default is to use adj of local mat)", "none", pcbddc->sub_schurs_use_useradj, &pcbddc->sub_schurs_use_useradj, NULL));
1099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_schur_exact", "Whether or not to use the exact Schur complement instead of the reduced one (which excludes size 1 cc)", "none", pcbddc->sub_schurs_exact_schur, &pcbddc->sub_schurs_exact_schur, NULL));
1109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_deluxe_zerorows", "Zero rows and columns of deluxe operators associated with primal dofs", "none", pcbddc->deluxe_zerorows, &pcbddc->deluxe_zerorows, NULL));
1119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_deluxe_singlemat", "Collapse deluxe operators", "none", pcbddc->deluxe_singlemat, &pcbddc->deluxe_singlemat, NULL));
1129566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_adaptive_userdefined", "Use user-defined constraints (should be attached via MatSetNearNullSpace to pmat) in addition to those adaptively generated", "none", pcbddc->adaptive_userdefined, &pcbddc->adaptive_userdefined, NULL));
113bd2a564bSStefano Zampini   nt = 2;
1149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRealArray("-pc_bddc_adaptive_threshold", "Thresholds to be used for adaptive selection of constraints", "none", pcbddc->adaptive_threshold, &nt, NULL));
115bd2a564bSStefano Zampini   if (nt == 1) pcbddc->adaptive_threshold[1] = pcbddc->adaptive_threshold[0];
1169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_adaptive_nmin", "Minimum number of constraints per connected components", "none", pcbddc->adaptive_nmin, &pcbddc->adaptive_nmin, NULL));
1179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_adaptive_nmax", "Maximum number of constraints per connected components", "none", pcbddc->adaptive_nmax, &pcbddc->adaptive_nmax, NULL));
1189566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_symmetric", "Symmetric computation of primal basis functions", "none", pcbddc->symmetric_primal, &pcbddc->symmetric_primal, NULL));
1199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_coarse_adj", "Number of processors where to map the coarse adjacency list", "none", pcbddc->coarse_adj_red, &pcbddc->coarse_adj_red, NULL));
1209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_benign_trick", "Apply the benign subspace trick to saddle point problems with discontinuous pressures", "none", pcbddc->benign_saddle_point, &pcbddc->benign_saddle_point, NULL));
1219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_benign_change", "Compute the pressure change of basis explicitly", "none", pcbddc->benign_change_explicit, &pcbddc->benign_change_explicit, NULL));
1229566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_benign_compute_correction", "Compute the benign correction during PreSolve", "none", pcbddc->benign_compute_correction, &pcbddc->benign_compute_correction, NULL));
1239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_nonetflux", "Automatic computation of no-net-flux quadrature weights", "none", pcbddc->compute_nonetflux, &pcbddc->compute_nonetflux, NULL));
1249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_detect_disconnected", "Detects disconnected subdomains", "none", pcbddc->detect_disconnected, &pcbddc->detect_disconnected, NULL));
1259566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_detect_disconnected_filter", "Filters out small entries in the local matrix when detecting disconnected subdomains", "none", pcbddc->detect_disconnected_filter, &pcbddc->detect_disconnected_filter, NULL));
1269566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_eliminate_dirichlet", "Whether or not we want to eliminate dirichlet dofs during presolve", "none", pcbddc->eliminate_dirdofs, &pcbddc->eliminate_dirdofs, NULL));
127d0609cedSBarry Smith   PetscOptionsHeadEnd();
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));
2589566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
259e9627c49SStefano Zampini 
260fbad9177SStefano Zampini     /* the coarse problem can be handled by a different communicator */
261e9627c49SStefano Zampini     if (pcbddc->coarse_ksp) color = 1;
262e9627c49SStefano Zampini     else color = 0;
2639566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
2649566063dSJacob Faibussowitsch     PetscCall(PetscSubcommCreate(PetscObjectComm((PetscObject)pc), &subcomm));
2659566063dSJacob Faibussowitsch     PetscCall(PetscSubcommSetNumber(subcomm, PetscMin(size, 2)));
2669566063dSJacob Faibussowitsch     PetscCall(PetscSubcommSetTypeGeneral(subcomm, color, rank));
2679566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetSubViewer(viewer, PetscSubcommChild(subcomm), &subviewer));
268e9627c49SStefano Zampini     if (color == 1) {
2699566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(subviewer, "--- Coarse solver\n"));
2709566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(subviewer));
2719566063dSJacob Faibussowitsch       PetscCall(KSPView(pcbddc->coarse_ksp, subviewer));
2729566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(subviewer));
2739566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(subviewer));
274e9627c49SStefano Zampini     }
2759566063dSJacob Faibussowitsch     PetscCall(PetscViewerRestoreSubViewer(viewer, PetscSubcommChild(subcomm), &subviewer));
2769566063dSJacob Faibussowitsch     PetscCall(PetscSubcommDestroy(&subcomm));
2779566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
278e9627c49SStefano Zampini   }
2793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2806b78500eSPatrick Sanan }
281a13144ffSStefano Zampini 
282d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDiscreteGradient_BDDC(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
283d71ae5a4SJacob Faibussowitsch {
284a13144ffSStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
285a13144ffSStefano Zampini 
286a13144ffSStefano Zampini   PetscFunctionBegin;
2879566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)G));
2889566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->discretegradient));
289a13144ffSStefano Zampini   pcbddc->discretegradient = G;
290a13144ffSStefano Zampini   pcbddc->nedorder         = order > 0 ? order : -order;
291495a2a07SStefano Zampini   pcbddc->nedfield         = field;
2921e0482f5SStefano Zampini   pcbddc->nedglobal        = global;
2931e0482f5SStefano Zampini   pcbddc->conforming       = conforming;
2943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
295a13144ffSStefano Zampini }
296a13144ffSStefano Zampini 
297a13144ffSStefano Zampini /*@
29898ad52f2SBarry Smith   PCBDDCSetDiscreteGradient - Sets the discrete gradient to be used by the `PCBDDC` preconditioner
299a13144ffSStefano Zampini 
300c3339decSBarry Smith   Collective
301a13144ffSStefano Zampini 
302a13144ffSStefano Zampini   Input Parameters:
303a13144ffSStefano Zampini + pc         - the preconditioning context
304f1580f4eSBarry Smith . G          - the discrete gradient matrix (in `MATAIJ` format)
305a13144ffSStefano Zampini . order      - the order of the Nedelec space (1 for the lowest order)
306495a2a07SStefano Zampini . field      - the field id of the Nedelec dofs (not used if the fields have not been specified)
30798ad52f2SBarry Smith . global     - the type of global ordering for the rows of `G`
308a13144ffSStefano Zampini - conforming - whether the mesh is conforming or not
309a13144ffSStefano Zampini 
310a13144ffSStefano Zampini   Level: advanced
311a13144ffSStefano Zampini 
312f1580f4eSBarry Smith   Note:
31320f4b53cSBarry Smith   The discrete gradient matrix `G` is used to analyze the subdomain edges, and it should not contain any zero entry.
314495a2a07SStefano Zampini   For variable order spaces, the order should be set to zero.
31598ad52f2SBarry Smith   If `global` is `PETSC_TRUE`, the rows of `G` should be given in global ordering for the whole dofs;
31698ad52f2SBarry Smith   if `PETSC_FALSE`, the ordering should be global for the Nedelec field.
3171e0482f5SStefano Zampini   In the latter case, it should hold gid[i] < gid[j] iff geid[i] < geid[j], with gid the global orderding for all the dofs
3181e0482f5SStefano Zampini   and geid the one for the Nedelec field.
319a13144ffSStefano Zampini 
320f1580f4eSBarry Smith .seealso: `PCBDDC`, `PCBDDCSetDofsSplitting()`, `PCBDDCSetDofsSplittingLocal()`, `MATAIJ`, `PCBDDCSetDivergenceMat()`
321a13144ffSStefano Zampini @*/
322d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDiscreteGradient(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
323d71ae5a4SJacob Faibussowitsch {
324a13144ffSStefano Zampini   PetscFunctionBegin;
325a13144ffSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
326a13144ffSStefano Zampini   PetscValidHeaderSpecific(G, MAT_CLASSID, 2);
327a13144ffSStefano Zampini   PetscValidLogicalCollectiveInt(pc, order, 3);
3281e0482f5SStefano Zampini   PetscValidLogicalCollectiveInt(pc, field, 4);
3291e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc, global, 5);
3301e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc, conforming, 6);
3311e0482f5SStefano Zampini   PetscCheckSameComm(pc, 1, G, 2);
332cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDiscreteGradient_C", (PC, Mat, PetscInt, PetscInt, PetscBool, PetscBool), (pc, G, order, field, global, conforming));
3333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
334a13144ffSStefano Zampini }
335a13144ffSStefano Zampini 
336d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDivergenceMat_BDDC(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
337d71ae5a4SJacob Faibussowitsch {
338a198735bSStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
3396b78500eSPatrick Sanan 
340a198735bSStefano Zampini   PetscFunctionBegin;
3419566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)divudotp));
3429566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->divudotp));
343a198735bSStefano Zampini   pcbddc->divudotp          = divudotp;
3448ae0ca82SStefano Zampini   pcbddc->divudotp_trans    = trans;
345a198735bSStefano Zampini   pcbddc->compute_nonetflux = PETSC_TRUE;
346a198735bSStefano Zampini   if (vl2l) {
3479566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)vl2l));
3489566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&pcbddc->divudotp_vl2l));
349a198735bSStefano Zampini     pcbddc->divudotp_vl2l = vl2l;
350a198735bSStefano Zampini   }
3513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
352a198735bSStefano Zampini }
3533d996552SStefano Zampini 
354a198735bSStefano Zampini /*@
35598ad52f2SBarry Smith   PCBDDCSetDivergenceMat - Sets the linear operator representing \int_\Omega \div {\bf u} \cdot p dx for the `PCBDDC` preconditioner
356a198735bSStefano Zampini 
357c3339decSBarry Smith   Collective
358a198735bSStefano Zampini 
359a198735bSStefano Zampini   Input Parameters:
360a198735bSStefano Zampini + pc       - the preconditioning context
361f1580f4eSBarry Smith . divudotp - the matrix (must be of type `MATIS`)
36298ad52f2SBarry Smith . trans    - if `PETSC_FALSE` (resp. `PETSC_TRUE`), then pressures are in the test (trial) space and velocities are in the trial (test) space.
36398ad52f2SBarry Smith - vl2l     - optional index set describing the local (wrt the local matrix in `divudotp`) to local (wrt the local matrix
364f1580f4eSBarry Smith    in the preconditioning matrix) map for the velocities
365a198735bSStefano Zampini 
366a198735bSStefano Zampini   Level: advanced
367a198735bSStefano Zampini 
36895452b02SPatrick Sanan   Notes:
36995452b02SPatrick Sanan   This auxiliary matrix is used to compute quadrature weights representing the net-flux across subdomain boundaries
370f1580f4eSBarry Smith 
37198ad52f2SBarry Smith   If `vl2l` is `NULL`, the local ordering for velocities in `divudotp` should match that of the preconditioning matrix
372a198735bSStefano Zampini 
373f1580f4eSBarry Smith .seealso: `PCBDDC`, `PCBDDCSetDiscreteGradient()`
374a198735bSStefano Zampini @*/
375d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDivergenceMat(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
376d71ae5a4SJacob Faibussowitsch {
377a198735bSStefano Zampini   PetscBool ismatis;
378a198735bSStefano Zampini 
379a198735bSStefano Zampini   PetscFunctionBegin;
380a198735bSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
381a198735bSStefano Zampini   PetscValidHeaderSpecific(divudotp, MAT_CLASSID, 2);
382a198735bSStefano Zampini   PetscCheckSameComm(pc, 1, divudotp, 2);
3838ae0ca82SStefano Zampini   PetscValidLogicalCollectiveBool(pc, trans, 3);
3841b24a7afSStefano Zampini   if (vl2l) PetscValidHeaderSpecific(vl2l, IS_CLASSID, 4);
3859566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)divudotp, MATIS, &ismatis));
38628b400f6SJacob Faibussowitsch   PetscCheck(ismatis, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Divergence matrix needs to be of type MATIS");
387cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDivergenceMat_C", (PC, Mat, PetscBool, IS), (pc, divudotp, trans, vl2l));
3883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
389a198735bSStefano Zampini }
3902d505d7fSStefano Zampini 
391d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change, PetscBool interior)
392d71ae5a4SJacob Faibussowitsch {
393b9b85e73SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
394b9b85e73SStefano Zampini 
395b9b85e73SStefano Zampini   PetscFunctionBegin;
3969566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)change));
3979566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->user_ChangeOfBasisMatrix));
398b9b85e73SStefano Zampini   pcbddc->user_ChangeOfBasisMatrix = change;
3991dd7afcfSStefano Zampini   pcbddc->change_interior          = interior;
4003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
401b9b85e73SStefano Zampini }
40232fe681dSStefano Zampini 
403b9b85e73SStefano Zampini /*@
404906d46d4SStefano Zampini   PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs
405b9b85e73SStefano Zampini 
406c3339decSBarry Smith   Collective
407b9b85e73SStefano Zampini 
408b9b85e73SStefano Zampini   Input Parameters:
409b9b85e73SStefano Zampini + pc       - the preconditioning context
4101dd7afcfSStefano Zampini . change   - the change of basis matrix
4111dd7afcfSStefano Zampini - interior - whether or not the change of basis modifies interior dofs
412b9b85e73SStefano Zampini 
413b9b85e73SStefano Zampini   Level: intermediate
414b9b85e73SStefano Zampini 
415db781477SPatrick Sanan .seealso: `PCBDDC`
416b9b85e73SStefano Zampini @*/
417d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change, PetscBool interior)
418d71ae5a4SJacob Faibussowitsch {
419b9b85e73SStefano Zampini   PetscFunctionBegin;
420b9b85e73SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
421b9b85e73SStefano Zampini   PetscValidHeaderSpecific(change, MAT_CLASSID, 2);
422906d46d4SStefano Zampini   PetscCheckSameComm(pc, 1, change, 2);
423906d46d4SStefano Zampini   if (pc->mat) {
424906d46d4SStefano Zampini     PetscInt rows_c, cols_c, rows, cols;
4259566063dSJacob Faibussowitsch     PetscCall(MatGetSize(pc->mat, &rows, &cols));
4269566063dSJacob Faibussowitsch     PetscCall(MatGetSize(change, &rows_c, &cols_c));
42763a3b9bcSJacob Faibussowitsch     PetscCheck(rows_c == rows, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Invalid number of rows for change of basis matrix! %" PetscInt_FMT " != %" PetscInt_FMT, rows_c, rows);
42863a3b9bcSJacob Faibussowitsch     PetscCheck(cols_c == cols, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Invalid number of columns for change of basis matrix! %" PetscInt_FMT " != %" PetscInt_FMT, cols_c, cols);
4299566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(pc->mat, &rows, &cols));
4309566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(change, &rows_c, &cols_c));
43163a3b9bcSJacob Faibussowitsch     PetscCheck(rows_c == rows, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Invalid number of local rows for change of basis matrix! %" PetscInt_FMT " != %" PetscInt_FMT, rows_c, rows);
43263a3b9bcSJacob Faibussowitsch     PetscCheck(cols_c == cols, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Invalid number of local columns for change of basis matrix! %" PetscInt_FMT " != %" PetscInt_FMT, cols_c, cols);
433906d46d4SStefano Zampini   }
434cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetChangeOfBasisMat_C", (PC, Mat, PetscBool), (pc, change, interior));
4353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
436b9b85e73SStefano Zampini }
4372d505d7fSStefano Zampini 
438d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetPrimalVerticesIS_BDDC(PC pc, IS PrimalVertices)
439d71ae5a4SJacob Faibussowitsch {
44030368db7SStefano Zampini   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
44156282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
44230368db7SStefano Zampini 
44330368db7SStefano Zampini   PetscFunctionBegin;
4449566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)PrimalVertices));
44548a46eb9SPierre Jolivet   if (pcbddc->user_primal_vertices) PetscCall(ISEqual(PrimalVertices, pcbddc->user_primal_vertices, &isequal));
4469566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices));
4479566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local));
44830368db7SStefano Zampini   pcbddc->user_primal_vertices = PrimalVertices;
44956282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
4503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
45130368db7SStefano Zampini }
452ab8c8b98SStefano Zampini 
45330368db7SStefano Zampini /*@
454f1580f4eSBarry Smith   PCBDDCSetPrimalVerticesIS - Set additional user defined primal vertices in `PCBDDC`
45530368db7SStefano Zampini 
45630368db7SStefano Zampini   Collective
45730368db7SStefano Zampini 
45830368db7SStefano Zampini   Input Parameters:
45930368db7SStefano Zampini + pc             - the preconditioning context
46030368db7SStefano Zampini - PrimalVertices - index set of primal vertices in global numbering (can be empty)
46130368db7SStefano Zampini 
46230368db7SStefano Zampini   Level: intermediate
46330368db7SStefano Zampini 
464f1580f4eSBarry Smith   Note:
46530368db7SStefano Zampini   Any process can list any global node
46630368db7SStefano Zampini 
467db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`, `PCBDDCGetPrimalVerticesLocalIS()`
46830368db7SStefano Zampini @*/
469d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetPrimalVerticesIS(PC pc, IS PrimalVertices)
470d71ae5a4SJacob Faibussowitsch {
47130368db7SStefano Zampini   PetscFunctionBegin;
47230368db7SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
47330368db7SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices, IS_CLASSID, 2);
47430368db7SStefano Zampini   PetscCheckSameComm(pc, 1, PrimalVertices, 2);
475cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetPrimalVerticesIS_C", (PC, IS), (pc, PrimalVertices));
4763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
47730368db7SStefano Zampini }
4782d505d7fSStefano Zampini 
479d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetPrimalVerticesIS_BDDC(PC pc, IS *is)
480d71ae5a4SJacob Faibussowitsch {
4813100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
4823100ebe3SStefano Zampini 
4833100ebe3SStefano Zampini   PetscFunctionBegin;
4843100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices;
4853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4863100ebe3SStefano Zampini }
4873100ebe3SStefano Zampini 
4883100ebe3SStefano Zampini /*@
489f1580f4eSBarry Smith   PCBDDCGetPrimalVerticesIS - Get user defined primal vertices set with `PCBDDCSetPrimalVerticesIS()`
4903100ebe3SStefano Zampini 
4913100ebe3SStefano Zampini   Collective
4923100ebe3SStefano Zampini 
493f1580f4eSBarry Smith   Input Parameter:
4943100ebe3SStefano Zampini . pc - the preconditioning context
4953100ebe3SStefano Zampini 
496f1580f4eSBarry Smith   Output Parameter:
49720f4b53cSBarry Smith . is - index set of primal vertices in global numbering (`NULL` if not set)
4983100ebe3SStefano Zampini 
4993100ebe3SStefano Zampini   Level: intermediate
5003100ebe3SStefano Zampini 
501db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`, `PCBDDCGetPrimalVerticesLocalIS()`
5023100ebe3SStefano Zampini @*/
503d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetPrimalVerticesIS(PC pc, IS *is)
504d71ae5a4SJacob Faibussowitsch {
5053100ebe3SStefano Zampini   PetscFunctionBegin;
5063100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
5073100ebe3SStefano Zampini   PetscValidPointer(is, 2);
508cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetPrimalVerticesIS_C", (PC, IS *), (pc, is));
5093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5103100ebe3SStefano Zampini }
5113100ebe3SStefano Zampini 
512d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
513d71ae5a4SJacob Faibussowitsch {
514674ae819SStefano Zampini   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
51556282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
5161e6b0712SBarry Smith 
517674ae819SStefano Zampini   PetscFunctionBegin;
5189566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)PrimalVertices));
51948a46eb9SPierre Jolivet   if (pcbddc->user_primal_vertices_local) PetscCall(ISEqual(PrimalVertices, pcbddc->user_primal_vertices_local, &isequal));
5209566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices));
5219566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local));
52230368db7SStefano Zampini   pcbddc->user_primal_vertices_local = PrimalVertices;
52356282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
5243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
525674ae819SStefano Zampini }
5263100ebe3SStefano Zampini 
527674ae819SStefano Zampini /*@
528f1580f4eSBarry Smith   PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in `PCBDDC`
529674ae819SStefano Zampini 
53017eb1463SStefano Zampini   Collective
531674ae819SStefano Zampini 
532674ae819SStefano Zampini   Input Parameters:
533674ae819SStefano Zampini + pc             - the preconditioning context
53417eb1463SStefano Zampini - PrimalVertices - index set of primal vertices in local numbering (can be empty)
535674ae819SStefano Zampini 
536674ae819SStefano Zampini   Level: intermediate
537674ae819SStefano Zampini 
538db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesLocalIS()`
539674ae819SStefano Zampini @*/
540d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
541d71ae5a4SJacob Faibussowitsch {
542674ae819SStefano Zampini   PetscFunctionBegin;
543674ae819SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
544674ae819SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices, IS_CLASSID, 2);
54517eb1463SStefano Zampini   PetscCheckSameComm(pc, 1, PrimalVertices, 2);
546cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetPrimalVerticesLocalIS_C", (PC, IS), (pc, PrimalVertices));
5473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
548674ae819SStefano Zampini }
5492d505d7fSStefano Zampini 
550d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetPrimalVerticesLocalIS_BDDC(PC pc, IS *is)
551d71ae5a4SJacob Faibussowitsch {
5523100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
5533100ebe3SStefano Zampini 
5543100ebe3SStefano Zampini   PetscFunctionBegin;
5553100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices_local;
5563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5573100ebe3SStefano Zampini }
5583100ebe3SStefano Zampini 
5593100ebe3SStefano Zampini /*@
560f1580f4eSBarry Smith   PCBDDCGetPrimalVerticesLocalIS - Get user defined primal vertices set with `PCBDDCSetPrimalVerticesLocalIS()`
5613100ebe3SStefano Zampini 
5623100ebe3SStefano Zampini   Collective
5633100ebe3SStefano Zampini 
564f1580f4eSBarry Smith   Input Parameter:
5653100ebe3SStefano Zampini . pc - the preconditioning context
5663100ebe3SStefano Zampini 
567f1580f4eSBarry Smith   Output Parameter:
56820f4b53cSBarry Smith . is - index set of primal vertices in local numbering (`NULL` if not set)
5693100ebe3SStefano Zampini 
5703100ebe3SStefano Zampini   Level: intermediate
5713100ebe3SStefano Zampini 
572db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`
5733100ebe3SStefano Zampini @*/
574d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetPrimalVerticesLocalIS(PC pc, IS *is)
575d71ae5a4SJacob Faibussowitsch {
5763100ebe3SStefano Zampini   PetscFunctionBegin;
5773100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
5783100ebe3SStefano Zampini   PetscValidPointer(is, 2);
579cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetPrimalVerticesLocalIS_C", (PC, IS *), (pc, is));
5803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5813100ebe3SStefano Zampini }
5823100ebe3SStefano Zampini 
583d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc, PetscInt k)
584d71ae5a4SJacob Faibussowitsch {
5854fad6a16SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
5864fad6a16SStefano Zampini 
5874fad6a16SStefano Zampini   PetscFunctionBegin;
5884fad6a16SStefano Zampini   pcbddc->coarsening_ratio = k;
5893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5904fad6a16SStefano Zampini }
5911e6b0712SBarry Smith 
5924fad6a16SStefano Zampini /*@
59398ad52f2SBarry Smith   PCBDDCSetCoarseningRatio - Set coarsening ratio used in the multi-level version of `PCBDDC`
5944fad6a16SStefano Zampini 
59520f4b53cSBarry Smith   Logically Collective
5964fad6a16SStefano Zampini 
5974fad6a16SStefano Zampini   Input Parameters:
5984fad6a16SStefano Zampini + pc - the preconditioning context
59928509bceSStefano Zampini - k  - coarsening ratio (H/h at the coarser level)
6004fad6a16SStefano Zampini 
601f1580f4eSBarry Smith   Options Database Key:
60298ad52f2SBarry Smith . -pc_bddc_coarsening_ratio <int> - Set the coarsening ratio used in multi-level coarsening
6034fad6a16SStefano Zampini 
6044fad6a16SStefano Zampini   Level: intermediate
6054fad6a16SStefano Zampini 
606f1580f4eSBarry Smith   Note:
60720f4b53cSBarry Smith   Approximately `k` subdomains at the finer level will be aggregated into a single subdomain at the coarser level
6084fad6a16SStefano Zampini 
609db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetLevels()`
6104fad6a16SStefano Zampini @*/
611d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetCoarseningRatio(PC pc, PetscInt k)
612d71ae5a4SJacob Faibussowitsch {
6134fad6a16SStefano Zampini   PetscFunctionBegin;
6144fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
6152b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc, k, 2);
616cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetCoarseningRatio_C", (PC, PetscInt), (pc, k));
6173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6184fad6a16SStefano Zampini }
6192b510759SStefano Zampini 
620b8ffe317SStefano Zampini /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */
621d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc, PetscBool flg)
622d71ae5a4SJacob Faibussowitsch {
623b8ffe317SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
624b8ffe317SStefano Zampini 
625b8ffe317SStefano Zampini   PetscFunctionBegin;
62685c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = flg;
6273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
628b8ffe317SStefano Zampini }
629b8ffe317SStefano Zampini 
630d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc, PetscBool flg)
631d71ae5a4SJacob Faibussowitsch {
6322b510759SStefano Zampini   PetscFunctionBegin;
6332b510759SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
634b8ffe317SStefano Zampini   PetscValidLogicalCollectiveBool(pc, flg, 2);
635cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetUseExactDirichlet_C", (PC, PetscBool), (pc, flg));
6363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6372b510759SStefano Zampini }
6381e6b0712SBarry Smith 
639d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc, PetscInt level)
640d71ae5a4SJacob Faibussowitsch {
6414fad6a16SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
6424fad6a16SStefano Zampini 
6434fad6a16SStefano Zampini   PetscFunctionBegin;
6442b510759SStefano Zampini   pcbddc->current_level = level;
6453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6464fad6a16SStefano Zampini }
6471e6b0712SBarry Smith 
648d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetLevel(PC pc, PetscInt level)
649d71ae5a4SJacob Faibussowitsch {
650b8ffe317SStefano Zampini   PetscFunctionBegin;
651b8ffe317SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
652b8ffe317SStefano Zampini   PetscValidLogicalCollectiveInt(pc, level, 2);
653cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetLevel_C", (PC, PetscInt), (pc, level));
6543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
655b8ffe317SStefano Zampini }
656b8ffe317SStefano Zampini 
657d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc, PetscInt levels)
658d71ae5a4SJacob Faibussowitsch {
6592b510759SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
6602b510759SStefano Zampini 
6612b510759SStefano Zampini   PetscFunctionBegin;
6627827d75bSBarry Smith   PetscCheck(levels < PETSC_PCBDDC_MAXLEVELS, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Maximum number of additional levels for BDDC is %d", PETSC_PCBDDC_MAXLEVELS - 1);
6632b510759SStefano Zampini   pcbddc->max_levels = levels;
6643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6652b510759SStefano Zampini }
6662b510759SStefano Zampini 
6674fad6a16SStefano Zampini /*@
668f1580f4eSBarry Smith   PCBDDCSetLevels - Sets the maximum number of additional levels allowed for multilevel `PCBDDC`
6694fad6a16SStefano Zampini 
67020f4b53cSBarry Smith   Logically Collective
6714fad6a16SStefano Zampini 
6724fad6a16SStefano Zampini   Input Parameters:
6734fad6a16SStefano Zampini + pc     - the preconditioning context
67437ebbdf7SStefano Zampini - levels - the maximum number of levels
6754fad6a16SStefano Zampini 
676f1580f4eSBarry Smith   Options Database Key:
67767b8a455SSatish Balay . -pc_bddc_levels <int> - Set maximum number of levels for multilevel
6784fad6a16SStefano Zampini 
6794fad6a16SStefano Zampini   Level: intermediate
6804fad6a16SStefano Zampini 
681f1580f4eSBarry Smith   Note:
68298ad52f2SBarry Smith   The default value is 0, that gives the classical two-levels BDDC algorithm
6834fad6a16SStefano Zampini 
684db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetCoarseningRatio()`
6854fad6a16SStefano Zampini @*/
686d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetLevels(PC pc, PetscInt levels)
687d71ae5a4SJacob Faibussowitsch {
6884fad6a16SStefano Zampini   PetscFunctionBegin;
6894fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
6902b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc, levels, 2);
691cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetLevels_C", (PC, PetscInt), (pc, levels));
6923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6934fad6a16SStefano Zampini }
6941e6b0712SBarry Smith 
695d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc, IS DirichletBoundaries)
696d71ae5a4SJacob Faibussowitsch {
6973b03a366Sstefano_zampini   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
69856282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
6993b03a366Sstefano_zampini 
7003b03a366Sstefano_zampini   PetscFunctionBegin;
7019566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)DirichletBoundaries));
70248a46eb9SPierre Jolivet   if (pcbddc->DirichletBoundaries) PetscCall(ISEqual(DirichletBoundaries, pcbddc->DirichletBoundaries, &isequal));
703a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
7049566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal));
7059566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundaries));
70636e030ebSStefano Zampini   pcbddc->DirichletBoundaries = DirichletBoundaries;
70756282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7093b03a366Sstefano_zampini }
7101e6b0712SBarry Smith 
7113b03a366Sstefano_zampini /*@
71298ad52f2SBarry Smith   PCBDDCSetDirichletBoundaries - Set the `IS` defining Dirichlet boundaries for the global problem.
7133b03a366Sstefano_zampini 
714785d1243SStefano Zampini   Collective
7153b03a366Sstefano_zampini 
7163b03a366Sstefano_zampini   Input Parameters:
7173b03a366Sstefano_zampini + pc                  - the preconditioning context
71820f4b53cSBarry Smith - DirichletBoundaries - parallel `IS` defining the Dirichlet boundaries
7193b03a366Sstefano_zampini 
7203b03a366Sstefano_zampini   Level: intermediate
7213b03a366Sstefano_zampini 
722f1580f4eSBarry Smith   Note:
723f1580f4eSBarry Smith   Provide the information if you used `MatZeroRows()` or `MatZeroRowsColumns()`. Any process can list any global node
7243b03a366Sstefano_zampini 
725db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetDirichletBoundariesLocal()`, `MatZeroRows()`, `MatZeroRowsColumns()`
7263b03a366Sstefano_zampini @*/
727d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc, IS DirichletBoundaries)
728d71ae5a4SJacob Faibussowitsch {
7293b03a366Sstefano_zampini   PetscFunctionBegin;
7303b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
731674ae819SStefano Zampini   PetscValidHeaderSpecific(DirichletBoundaries, IS_CLASSID, 2);
732785d1243SStefano Zampini   PetscCheckSameComm(pc, 1, DirichletBoundaries, 2);
733cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDirichletBoundaries_C", (PC, IS), (pc, DirichletBoundaries));
7343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7353b03a366Sstefano_zampini }
7361e6b0712SBarry Smith 
737d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc, IS DirichletBoundaries)
738d71ae5a4SJacob Faibussowitsch {
7393b03a366Sstefano_zampini   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
74056282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
7413b03a366Sstefano_zampini 
7423b03a366Sstefano_zampini   PetscFunctionBegin;
7439566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)DirichletBoundaries));
74448a46eb9SPierre Jolivet   if (pcbddc->DirichletBoundariesLocal) PetscCall(ISEqual(DirichletBoundaries, pcbddc->DirichletBoundariesLocal, &isequal));
745a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
7469566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal));
7479566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundaries));
748785d1243SStefano Zampini   pcbddc->DirichletBoundariesLocal = DirichletBoundaries;
74956282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7513b03a366Sstefano_zampini }
7523b03a366Sstefano_zampini 
7533b03a366Sstefano_zampini /*@
75498ad52f2SBarry Smith   PCBDDCSetDirichletBoundariesLocal - Set the `IS` defining Dirichlet boundaries for the global problem in local ordering.
7553b03a366Sstefano_zampini 
756785d1243SStefano Zampini   Collective
7573b03a366Sstefano_zampini 
7583b03a366Sstefano_zampini   Input Parameters:
7593b03a366Sstefano_zampini + pc                  - the preconditioning context
76020f4b53cSBarry Smith - DirichletBoundaries - parallel `IS` defining the Dirichlet boundaries (in local ordering)
7613b03a366Sstefano_zampini 
7623b03a366Sstefano_zampini   Level: intermediate
7633b03a366Sstefano_zampini 
764db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetDirichletBoundaries()`, `MatZeroRows()`, `MatZeroRowsColumns()`
7653b03a366Sstefano_zampini @*/
766d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc, IS DirichletBoundaries)
767d71ae5a4SJacob Faibussowitsch {
7683b03a366Sstefano_zampini   PetscFunctionBegin;
7693b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
7703b03a366Sstefano_zampini   PetscValidHeaderSpecific(DirichletBoundaries, IS_CLASSID, 2);
77182ba6b80SStefano Zampini   PetscCheckSameComm(pc, 1, DirichletBoundaries, 2);
772cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDirichletBoundariesLocal_C", (PC, IS), (pc, DirichletBoundaries));
7733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7743b03a366Sstefano_zampini }
7753b03a366Sstefano_zampini 
776d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc, IS NeumannBoundaries)
777d71ae5a4SJacob Faibussowitsch {
7780c7d97c5SJed Brown   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
77956282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
7800c7d97c5SJed Brown 
7810c7d97c5SJed Brown   PetscFunctionBegin;
7829566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries));
78348a46eb9SPierre Jolivet   if (pcbddc->NeumannBoundaries) PetscCall(ISEqual(NeumannBoundaries, pcbddc->NeumannBoundaries, &isequal));
784a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
7859566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal));
7869566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundaries));
78736e030ebSStefano Zampini   pcbddc->NeumannBoundaries = NeumannBoundaries;
78856282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7900c7d97c5SJed Brown }
7911e6b0712SBarry Smith 
79257527edcSJed Brown /*@
79398ad52f2SBarry Smith   PCBDDCSetNeumannBoundaries - Set the `IS` defining Neumann boundaries for the global problem.
79457527edcSJed Brown 
795c3339decSBarry Smith   Collective
79657527edcSJed Brown 
79757527edcSJed Brown   Input Parameters:
79857527edcSJed Brown + pc                - the preconditioning context
79920f4b53cSBarry Smith - NeumannBoundaries - parallel `IS` defining the Neumann boundaries
80057527edcSJed Brown 
80157527edcSJed Brown   Level: intermediate
80257527edcSJed Brown 
803f1580f4eSBarry Smith   Note:
8040f202f7eSStefano Zampini   Any process can list any global node
80557527edcSJed Brown 
806db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetNeumannBoundariesLocal()`
80757527edcSJed Brown @*/
808d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc, IS NeumannBoundaries)
809d71ae5a4SJacob Faibussowitsch {
8100c7d97c5SJed Brown   PetscFunctionBegin;
8110c7d97c5SJed Brown   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
812674ae819SStefano Zampini   PetscValidHeaderSpecific(NeumannBoundaries, IS_CLASSID, 2);
813785d1243SStefano Zampini   PetscCheckSameComm(pc, 1, NeumannBoundaries, 2);
814cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetNeumannBoundaries_C", (PC, IS), (pc, NeumannBoundaries));
8153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81653cdbc3dSStefano Zampini }
8171e6b0712SBarry Smith 
818d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc, IS NeumannBoundaries)
819d71ae5a4SJacob Faibussowitsch {
8200c7d97c5SJed Brown   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
82156282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
8220c7d97c5SJed Brown 
8230c7d97c5SJed Brown   PetscFunctionBegin;
8249566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries));
82548a46eb9SPierre Jolivet   if (pcbddc->NeumannBoundariesLocal) PetscCall(ISEqual(NeumannBoundaries, pcbddc->NeumannBoundariesLocal, &isequal));
826a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
8279566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal));
8289566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundaries));
829785d1243SStefano Zampini   pcbddc->NeumannBoundariesLocal = NeumannBoundaries;
83056282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
8313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8320c7d97c5SJed Brown }
8330c7d97c5SJed Brown 
8340c7d97c5SJed Brown /*@
83598ad52f2SBarry Smith   PCBDDCSetNeumannBoundariesLocal - Set the `IS` defining Neumann boundaries for the global problem in local ordering.
8360c7d97c5SJed Brown 
837785d1243SStefano Zampini   Collective
8380c7d97c5SJed Brown 
8390c7d97c5SJed Brown   Input Parameters:
8400c7d97c5SJed Brown + pc                - the preconditioning context
84120f4b53cSBarry Smith - NeumannBoundaries - parallel `IS` defining the subdomain part of Neumann boundaries (in local ordering)
8420c7d97c5SJed Brown 
8430c7d97c5SJed Brown   Level: intermediate
8440c7d97c5SJed Brown 
845f1580f4eSBarry Smith .seealso: `PCBDDC`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCGetDirichletBoundaries()`
8460c7d97c5SJed Brown @*/
847d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc, IS NeumannBoundaries)
848d71ae5a4SJacob Faibussowitsch {
8490c7d97c5SJed Brown   PetscFunctionBegin;
8500c7d97c5SJed Brown   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
8510c7d97c5SJed Brown   PetscValidHeaderSpecific(NeumannBoundaries, IS_CLASSID, 2);
85282ba6b80SStefano Zampini   PetscCheckSameComm(pc, 1, NeumannBoundaries, 2);
853cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetNeumannBoundariesLocal_C", (PC, IS), (pc, NeumannBoundaries));
8543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
85553cdbc3dSStefano Zampini }
85653cdbc3dSStefano Zampini 
857d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc, IS *DirichletBoundaries)
858d71ae5a4SJacob Faibussowitsch {
859da1bb401SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
860da1bb401SStefano Zampini 
861da1bb401SStefano Zampini   PetscFunctionBegin;
862da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
8633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
864da1bb401SStefano Zampini }
8651e6b0712SBarry Smith 
866da1bb401SStefano Zampini /*@
867f1580f4eSBarry Smith   PCBDDCGetDirichletBoundaries - Get parallel `IS` for Dirichlet boundaries
868da1bb401SStefano Zampini 
869785d1243SStefano Zampini   Collective
870785d1243SStefano Zampini 
871f1580f4eSBarry Smith   Input Parameter:
872785d1243SStefano Zampini . pc - the preconditioning context
873785d1243SStefano Zampini 
874f1580f4eSBarry Smith   Output Parameter:
875785d1243SStefano Zampini . DirichletBoundaries - index set defining the Dirichlet boundaries
876785d1243SStefano Zampini 
877785d1243SStefano Zampini   Level: intermediate
878785d1243SStefano Zampini 
879f1580f4eSBarry Smith   Note:
880f1580f4eSBarry Smith   The `IS` returned (if any) is the same passed in earlier by the user with `PCBDDCSetDirichletBoundaries()`
881785d1243SStefano Zampini 
882f1580f4eSBarry Smith .seealso: `PCBDDC`, `PCBDDCSetDirichletBoundaries()`
883785d1243SStefano Zampini @*/
884d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc, IS *DirichletBoundaries)
885d71ae5a4SJacob Faibussowitsch {
886785d1243SStefano Zampini   PetscFunctionBegin;
887785d1243SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
888cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetDirichletBoundaries_C", (PC, IS *), (pc, DirichletBoundaries));
8893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
890785d1243SStefano Zampini }
891785d1243SStefano Zampini 
892d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc, IS *DirichletBoundaries)
893d71ae5a4SJacob Faibussowitsch {
894785d1243SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
895785d1243SStefano Zampini 
896785d1243SStefano Zampini   PetscFunctionBegin;
897785d1243SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundariesLocal;
8983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
899785d1243SStefano Zampini }
900785d1243SStefano Zampini 
901da1bb401SStefano Zampini /*@
902f1580f4eSBarry Smith   PCBDDCGetDirichletBoundariesLocal - Get parallel `IS` for Dirichlet boundaries (in local ordering)
903da1bb401SStefano Zampini 
904785d1243SStefano Zampini   Collective
905da1bb401SStefano Zampini 
906f1580f4eSBarry Smith   Input Parameter:
90728509bceSStefano Zampini . pc - the preconditioning context
908da1bb401SStefano Zampini 
909f1580f4eSBarry Smith   Output Parameter:
91028509bceSStefano Zampini . DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
911da1bb401SStefano Zampini 
912da1bb401SStefano Zampini   Level: intermediate
913da1bb401SStefano Zampini 
914f1580f4eSBarry Smith   Note:
915f1580f4eSBarry Smith   The `IS` returned could be the same passed in earlier by the user (if provided with `PCBDDCSetDirichletBoundariesLocal()`)
916f1580f4eSBarry Smith   or a global-to-local map of the global `IS` (if provided with `PCBDDCSetDirichletBoundaries()`).
917f1580f4eSBarry Smith   In the latter case, the `IS` will be available only after `PCSetUp()`.
918da1bb401SStefano Zampini 
919f1580f4eSBarry Smith .seealso: `PCBDDC`, `PCBDDCGetDirichletBoundariesLocal()`, `PCBDDCGetDirichletBoundaries()`, `PCBDDCSetDirichletBoundaries()`
920da1bb401SStefano Zampini @*/
921d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc, IS *DirichletBoundaries)
922d71ae5a4SJacob Faibussowitsch {
923da1bb401SStefano Zampini   PetscFunctionBegin;
924da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
925cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetDirichletBoundariesLocal_C", (PC, IS *), (pc, DirichletBoundaries));
9263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
927da1bb401SStefano Zampini }
9281e6b0712SBarry Smith 
929d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc, IS *NeumannBoundaries)
930d71ae5a4SJacob Faibussowitsch {
93153cdbc3dSStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
93253cdbc3dSStefano Zampini 
93353cdbc3dSStefano Zampini   PetscFunctionBegin;
93453cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
9353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
93653cdbc3dSStefano Zampini }
9371e6b0712SBarry Smith 
93853cdbc3dSStefano Zampini /*@
939f1580f4eSBarry Smith   PCBDDCGetNeumannBoundaries - Get parallel `IS` for Neumann boundaries
94053cdbc3dSStefano Zampini 
941f1580f4eSBarry Smith   Not Collective
942785d1243SStefano Zampini 
943f1580f4eSBarry Smith   Input Parameter:
944785d1243SStefano Zampini . pc - the preconditioning context
945785d1243SStefano Zampini 
946f1580f4eSBarry Smith   Output Parameter:
947785d1243SStefano Zampini . NeumannBoundaries - index set defining the Neumann boundaries
948785d1243SStefano Zampini 
949785d1243SStefano Zampini   Level: intermediate
950785d1243SStefano Zampini 
951f1580f4eSBarry Smith   Note:
952f1580f4eSBarry Smith   The `IS` returned (if any) is the same passed in earlier by the user with `PCBDDCSetNeumannBoundaries()`
953785d1243SStefano Zampini 
954f1580f4eSBarry Smith .seealso: `PCBDDC`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCGetDirichletBoundaries()`, `PCBDDCSetDirichletBoundaries()`
955785d1243SStefano Zampini @*/
956d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc, IS *NeumannBoundaries)
957d71ae5a4SJacob Faibussowitsch {
958785d1243SStefano Zampini   PetscFunctionBegin;
959785d1243SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
960cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetNeumannBoundaries_C", (PC, IS *), (pc, NeumannBoundaries));
9613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
962785d1243SStefano Zampini }
963785d1243SStefano Zampini 
964d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc, IS *NeumannBoundaries)
965d71ae5a4SJacob Faibussowitsch {
966785d1243SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
967785d1243SStefano Zampini 
968785d1243SStefano Zampini   PetscFunctionBegin;
969785d1243SStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundariesLocal;
9703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
971785d1243SStefano Zampini }
972785d1243SStefano Zampini 
97353cdbc3dSStefano Zampini /*@
974f1580f4eSBarry Smith   PCBDDCGetNeumannBoundariesLocal - Get parallel `IS` for Neumann boundaries (in local ordering)
97553cdbc3dSStefano Zampini 
976f1580f4eSBarry Smith   Not Collective
97753cdbc3dSStefano Zampini 
978f1580f4eSBarry Smith   Input Parameter:
97928509bceSStefano Zampini . pc - the preconditioning context
98053cdbc3dSStefano Zampini 
981f1580f4eSBarry Smith   Output Parameter:
98228509bceSStefano Zampini . NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
98353cdbc3dSStefano Zampini 
98453cdbc3dSStefano Zampini   Level: intermediate
98553cdbc3dSStefano Zampini 
986f1580f4eSBarry Smith   Note:
987f1580f4eSBarry Smith   The `IS` returned could be the same passed in earlier by the user (if provided with `PCBDDCSetNeumannBoundariesLocal()`
988f1580f4eSBarry Smith   or a global-to-local map of the global `IS` (if provided with `PCBDDCSetNeumannBoundaries()`).
989f1580f4eSBarry Smith   In the latter case, the `IS` will be available after `PCSetUp()`.
99053cdbc3dSStefano Zampini 
991f1580f4eSBarry Smith .seealso: `PCBDDC``PCBDDCSetNeumannBoundaries()`, `PCBDDCSetNeumannBoundariesLocal)`, `PCBDDCGetNeumannBoundaries()`
99253cdbc3dSStefano Zampini @*/
993d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc, IS *NeumannBoundaries)
994d71ae5a4SJacob Faibussowitsch {
99553cdbc3dSStefano Zampini   PetscFunctionBegin;
99653cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
997cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetNeumannBoundariesLocal_C", (PC, IS *), (pc, NeumannBoundaries));
9983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9990c7d97c5SJed Brown }
10001e6b0712SBarry Smith 
1001d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs, const PetscInt xadj[], const PetscInt adjncy[], PetscCopyMode copymode)
1002d71ae5a4SJacob Faibussowitsch {
100336e030ebSStefano Zampini   PC_BDDC    *pcbddc    = (PC_BDDC *)pc->data;
1004da1bb401SStefano Zampini   PCBDDCGraph mat_graph = pcbddc->mat_graph;
100556282151SStefano Zampini   PetscBool   same_data = PETSC_FALSE;
100636e030ebSStefano Zampini 
100736e030ebSStefano Zampini   PetscFunctionBegin;
10088687889aSStefano Zampini   if (!nvtxs) {
100904194a47SStefano Zampini     if (copymode == PETSC_OWN_POINTER) {
10109566063dSJacob Faibussowitsch       PetscCall(PetscFree(xadj));
10119566063dSJacob Faibussowitsch       PetscCall(PetscFree(adjncy));
101204194a47SStefano Zampini     }
10139566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphResetCSR(mat_graph));
10143ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
10158687889aSStefano Zampini   }
101666da6bd7Sstefano_zampini   if (mat_graph->nvtxs == nvtxs && mat_graph->freecsr) { /* we own the data */
101756282151SStefano Zampini     if (mat_graph->xadj == xadj && mat_graph->adjncy == adjncy) same_data = PETSC_TRUE;
101856282151SStefano Zampini     if (!same_data && mat_graph->xadj[nvtxs] == xadj[nvtxs]) {
10199566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(xadj, mat_graph->xadj, nvtxs + 1, &same_data));
102048a46eb9SPierre Jolivet       if (same_data) PetscCall(PetscArraycmp(adjncy, mat_graph->adjncy, xadj[nvtxs], &same_data));
102156282151SStefano Zampini     }
102256282151SStefano Zampini   }
102356282151SStefano Zampini   if (!same_data) {
1024674ae819SStefano Zampini     /* free old CSR */
10259566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphResetCSR(mat_graph));
1026674ae819SStefano Zampini     /* get CSR into graph structure */
1027da1bb401SStefano Zampini     if (copymode == PETSC_COPY_VALUES) {
10289566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvtxs + 1, &mat_graph->xadj));
10299566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(xadj[nvtxs], &mat_graph->adjncy));
10309566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(mat_graph->xadj, xadj, nvtxs + 1));
10319566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(mat_graph->adjncy, adjncy, xadj[nvtxs]));
1032a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1033da1bb401SStefano Zampini     } else if (copymode == PETSC_OWN_POINTER) {
10341a83f524SJed Brown       mat_graph->xadj    = (PetscInt *)xadj;
10351a83f524SJed Brown       mat_graph->adjncy  = (PetscInt *)adjncy;
1036a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1037a1dbd327SStefano Zampini     } else if (copymode == PETSC_USE_POINTER) {
1038a1dbd327SStefano Zampini       mat_graph->xadj    = (PetscInt *)xadj;
1039a1dbd327SStefano Zampini       mat_graph->adjncy  = (PetscInt *)adjncy;
1040a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_FALSE;
104163a3b9bcSJacob Faibussowitsch     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported copy mode %d", copymode);
1042575ad6abSStefano Zampini     mat_graph->nvtxs_csr         = nvtxs;
104356282151SStefano Zampini     pcbddc->recompute_topography = PETSC_TRUE;
104456282151SStefano Zampini   }
10453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
104636e030ebSStefano Zampini }
10471e6b0712SBarry Smith 
104836e030ebSStefano Zampini /*@
104954fffbccSStefano Zampini   PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local degrees of freedom.
105036e030ebSStefano Zampini 
105136e030ebSStefano Zampini   Not collective
105236e030ebSStefano Zampini 
105336e030ebSStefano Zampini   Input Parameters:
105454fffbccSStefano Zampini + pc           - the preconditioning context.
105554fffbccSStefano Zampini . nvtxs        - number of local vertices of the graph (i.e., the number of local dofs).
105654fffbccSStefano Zampini . xadj, adjncy - the connectivity of the dofs in CSR format.
1057f1580f4eSBarry Smith - copymode     - supported modes are `PETSC_COPY_VALUES`, `PETSC_USE_POINTER` or `PETSC_OWN_POINTER`.
105836e030ebSStefano Zampini 
105936e030ebSStefano Zampini   Level: intermediate
106036e030ebSStefano Zampini 
1061f1580f4eSBarry Smith   Note:
106295452b02SPatrick Sanan   A dof is considered connected with all local dofs if xadj[dof+1]-xadj[dof] == 1 and adjncy[xadj[dof]] is negative.
106336e030ebSStefano Zampini 
106416b07851SJed Brown .seealso: `PCBDDC`, `PetscCopyMode`
106536e030ebSStefano Zampini @*/
1066d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc, PetscInt nvtxs, const PetscInt xadj[], const PetscInt adjncy[], PetscCopyMode copymode)
1067d71ae5a4SJacob Faibussowitsch {
10680a545947SLisandro Dalcin   void (*f)(void) = NULL;
106936e030ebSStefano Zampini 
107036e030ebSStefano Zampini   PetscFunctionBegin;
107136e030ebSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
10728687889aSStefano Zampini   if (nvtxs) {
1073674ae819SStefano Zampini     PetscValidIntPointer(xadj, 3);
10741633d1f0SStefano Zampini     if (xadj[nvtxs]) PetscValidIntPointer(adjncy, 4);
10758687889aSStefano Zampini   }
1076cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetLocalAdjacencyGraph_C", (PC, PetscInt, const PetscInt[], const PetscInt[], PetscCopyMode), (pc, nvtxs, xadj, adjncy, copymode));
1077575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
10789566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", &f));
1079575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
10809566063dSJacob Faibussowitsch     PetscCall(PetscFree(xadj));
10819566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjncy));
1082da1bb401SStefano Zampini   }
10833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
108436e030ebSStefano Zampini }
10851e6b0712SBarry Smith 
1086d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc, PetscInt n_is, IS ISForDofs[])
1087d71ae5a4SJacob Faibussowitsch {
108863602bcaSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC *)pc->data;
108963602bcaSStefano Zampini   PetscInt  i;
109056282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
109163602bcaSStefano Zampini 
109263602bcaSStefano Zampini   PetscFunctionBegin;
109356282151SStefano Zampini   if (pcbddc->n_ISForDofsLocal == n_is) {
109456282151SStefano Zampini     for (i = 0; i < n_is; i++) {
109556282151SStefano Zampini       PetscBool isequalt;
10969566063dSJacob Faibussowitsch       PetscCall(ISEqual(ISForDofs[i], pcbddc->ISForDofsLocal[i], &isequalt));
109756282151SStefano Zampini       if (!isequalt) break;
109856282151SStefano Zampini     }
109956282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
110056282151SStefano Zampini   }
110148a46eb9SPierre Jolivet   for (i = 0; i < n_is; i++) PetscCall(PetscObjectReference((PetscObject)ISForDofs[i]));
110263602bcaSStefano Zampini   /* Destroy ISes if they were already set */
110348a46eb9SPierre Jolivet   for (i = 0; i < pcbddc->n_ISForDofsLocal; i++) PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i]));
11049566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofsLocal));
1105a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
110648a46eb9SPierre Jolivet   for (i = 0; i < pcbddc->n_ISForDofs; i++) PetscCall(ISDestroy(&pcbddc->ISForDofs[i]));
11079566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofs));
110863602bcaSStefano Zampini   pcbddc->n_ISForDofs = 0;
110963602bcaSStefano Zampini   /* allocate space then set */
111048a46eb9SPierre Jolivet   if (n_is) PetscCall(PetscMalloc1(n_is, &pcbddc->ISForDofsLocal));
1111ad540459SPierre Jolivet   for (i = 0; i < n_is; i++) pcbddc->ISForDofsLocal[i] = ISForDofs[i];
111263602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = n_is;
111363602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
111456282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
11153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
111663602bcaSStefano Zampini }
111763602bcaSStefano Zampini 
111863602bcaSStefano Zampini /*@
111998ad52f2SBarry Smith   PCBDDCSetDofsSplittingLocal - Set the `IS` defining fields of the local subdomain matrix
112063602bcaSStefano Zampini 
112163602bcaSStefano Zampini   Collective
112263602bcaSStefano Zampini 
112363602bcaSStefano Zampini   Input Parameters:
112463602bcaSStefano Zampini + pc        - the preconditioning context
112598ad52f2SBarry Smith . n_is      - number of index sets defining the fields, must be the same on all MPI processes
1126f1580f4eSBarry Smith - ISForDofs - array of `IS` describing the fields in local ordering
112763602bcaSStefano Zampini 
112863602bcaSStefano Zampini   Level: intermediate
112963602bcaSStefano Zampini 
1130f1580f4eSBarry Smith   Note:
1131*feefa0e1SJacob Faibussowitsch   Not all nodes need to be listed, unlisted nodes will belong to the complement field.
113263602bcaSStefano Zampini 
1133f1580f4eSBarry Smith .seealso: `PCBDDC`, `PCBDDCSetDofsSplitting()`
113463602bcaSStefano Zampini @*/
1135d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc, PetscInt n_is, IS ISForDofs[])
1136d71ae5a4SJacob Faibussowitsch {
113763602bcaSStefano Zampini   PetscInt i;
113863602bcaSStefano Zampini 
113963602bcaSStefano Zampini   PetscFunctionBegin;
114063602bcaSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
114163602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc, n_is, 2);
114263602bcaSStefano Zampini   for (i = 0; i < n_is; i++) {
114363602bcaSStefano Zampini     PetscCheckSameComm(pc, 1, ISForDofs[i], 3);
114463602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i], IS_CLASSID, 3);
114563602bcaSStefano Zampini   }
1146cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDofsSplittingLocal_C", (PC, PetscInt, IS[]), (pc, n_is, ISForDofs));
11473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
114863602bcaSStefano Zampini }
114963602bcaSStefano Zampini 
1150d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc, PetscInt n_is, IS ISForDofs[])
1151d71ae5a4SJacob Faibussowitsch {
11529c0446d6SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC *)pc->data;
11539c0446d6SStefano Zampini   PetscInt  i;
115456282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
11559c0446d6SStefano Zampini 
11569c0446d6SStefano Zampini   PetscFunctionBegin;
115756282151SStefano Zampini   if (pcbddc->n_ISForDofs == n_is) {
115856282151SStefano Zampini     for (i = 0; i < n_is; i++) {
115956282151SStefano Zampini       PetscBool isequalt;
11609566063dSJacob Faibussowitsch       PetscCall(ISEqual(ISForDofs[i], pcbddc->ISForDofs[i], &isequalt));
116156282151SStefano Zampini       if (!isequalt) break;
116256282151SStefano Zampini     }
116356282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
116456282151SStefano Zampini   }
116548a46eb9SPierre Jolivet   for (i = 0; i < n_is; i++) PetscCall(PetscObjectReference((PetscObject)ISForDofs[i]));
1166da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
116748a46eb9SPierre Jolivet   for (i = 0; i < pcbddc->n_ISForDofs; i++) PetscCall(ISDestroy(&pcbddc->ISForDofs[i]));
11689566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofs));
1169a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
117048a46eb9SPierre Jolivet   for (i = 0; i < pcbddc->n_ISForDofsLocal; i++) PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i]));
11719566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofsLocal));
117263602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = 0;
1173da1bb401SStefano Zampini   /* allocate space then set */
117448a46eb9SPierre Jolivet   if (n_is) PetscCall(PetscMalloc1(n_is, &pcbddc->ISForDofs));
1175ad540459SPierre Jolivet   for (i = 0; i < n_is; i++) pcbddc->ISForDofs[i] = ISForDofs[i];
11769c0446d6SStefano Zampini   pcbddc->n_ISForDofs = n_is;
117763602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
117856282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
11793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11809c0446d6SStefano Zampini }
11811e6b0712SBarry Smith 
11829c0446d6SStefano Zampini /*@
118398ad52f2SBarry Smith   PCBDDCSetDofsSplitting - Set the `IS` defining fields of the global matrix
11849c0446d6SStefano Zampini 
118563602bcaSStefano Zampini   Collective
11869c0446d6SStefano Zampini 
11879c0446d6SStefano Zampini   Input Parameters:
11889c0446d6SStefano Zampini + pc        - the preconditioning context
11890f202f7eSStefano Zampini . n_is      - number of index sets defining the fields
119098ad52f2SBarry Smith - ISForDofs - array of `IS` describing the fields in global ordering
11919c0446d6SStefano Zampini 
11929c0446d6SStefano Zampini   Level: intermediate
11939c0446d6SStefano Zampini 
1194f1580f4eSBarry Smith   Note:
11950f202f7eSStefano Zampini   Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
11969c0446d6SStefano Zampini 
1197f1580f4eSBarry Smith .seealso: `PCBDDC`, `PCBDDCSetDofsSplittingLocal()`
11989c0446d6SStefano Zampini @*/
1199d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDofsSplitting(PC pc, PetscInt n_is, IS ISForDofs[])
1200d71ae5a4SJacob Faibussowitsch {
12012b510759SStefano Zampini   PetscInt i;
12029c0446d6SStefano Zampini 
12039c0446d6SStefano Zampini   PetscFunctionBegin;
12049c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
120563602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc, n_is, 2);
12062b510759SStefano Zampini   for (i = 0; i < n_is; i++) {
120763602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i], IS_CLASSID, 3);
1208a011d5a7Sstefano_zampini     PetscCheckSameComm(pc, 1, ISForDofs[i], 3);
12092b510759SStefano Zampini   }
1210cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDofsSplitting_C", (PC, PetscInt, IS[]), (pc, n_is, ISForDofs));
12113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12129c0446d6SStefano Zampini }
1213906d46d4SStefano Zampini 
1214534831adSStefano Zampini /*
1215534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
1216534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
12179c0446d6SStefano Zampini 
1218534831adSStefano Zampini    Input Parameter:
1219966d8056SPierre Jolivet +  pc - the preconditioner context
1220534831adSStefano Zampini 
1221f1580f4eSBarry Smith    Note:
1222534831adSStefano Zampini      The interface routine PCPreSolve() is not usually called directly by
1223534831adSStefano Zampini    the user, but instead is called by KSPSolve().
1224534831adSStefano Zampini */
1225d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1226d71ae5a4SJacob Faibussowitsch {
1227534831adSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC *)pc->data;
1228534831adSStefano Zampini   PC_IS    *pcis   = (PC_IS *)(pc->data);
12293972b0daSStefano Zampini   Vec       used_vec;
1230fcb54b1cSPierre Jolivet   PetscBool iscg, save_rhs = PETSC_TRUE, benign_correction_computed;
1231534831adSStefano Zampini 
1232534831adSStefano Zampini   PetscFunctionBegin;
12331f4df5f7SStefano Zampini   /* if we are working with CG, one dirichlet solve can be avoided during Krylov iterations */
123485c4d303SStefano Zampini   if (ksp) {
1235fcb54b1cSPierre Jolivet     PetscCall(PetscObjectTypeCompareAny((PetscObject)ksp, &iscg, KSPCG, KSPGROPPCG, KSPPIPECG, KSPPIPELCG, KSPPIPECGRR, ""));
123648a46eb9SPierre Jolivet     if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || !iscg || pc->mat != pc->pmat) PetscCall(PCBDDCSetUseExactDirichlet(pc, PETSC_FALSE));
123785c4d303SStefano Zampini   }
123848a46eb9SPierre Jolivet   if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || pc->mat != pc->pmat) PetscCall(PCBDDCSetUseExactDirichlet(pc, PETSC_FALSE));
12391f4df5f7SStefano Zampini 
124085c4d303SStefano Zampini   /* Creates parallel work vectors used in presolve */
124148a46eb9SPierre Jolivet   if (!pcbddc->original_rhs) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->original_rhs));
124248a46eb9SPierre Jolivet   if (!pcbddc->temp_solution) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->temp_solution));
12438d00608fSStefano Zampini 
124427b6a85dSStefano Zampini   pcbddc->temp_solution_used = PETSC_FALSE;
12453972b0daSStefano Zampini   if (x) {
12469566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)x));
12473972b0daSStefano Zampini     used_vec = x;
12488d00608fSStefano Zampini   } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */
12499566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pcbddc->temp_solution));
12503972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
12519566063dSJacob Faibussowitsch     PetscCall(VecSet(used_vec, 0.0));
125227b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
12539566063dSJacob Faibussowitsch     PetscCall(VecCopy(rhs, pcbddc->original_rhs));
1254266e20e9SStefano Zampini     save_rhs                  = PETSC_FALSE;
1255266e20e9SStefano Zampini     pcbddc->eliminate_dirdofs = PETSC_TRUE;
12563972b0daSStefano Zampini   }
12578efcfb23SStefano Zampini 
12588efcfb23SStefano Zampini   /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */
12593972b0daSStefano Zampini   if (ksp) {
1260a0cb1b98SStefano Zampini     /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */
12619566063dSJacob Faibussowitsch     PetscCall(KSPGetInitialGuessNonzero(ksp, &pcbddc->ksp_guess_nonzero));
126248a46eb9SPierre Jolivet     if (!pcbddc->ksp_guess_nonzero) PetscCall(VecSet(used_vec, 0.0));
12633972b0daSStefano Zampini   }
12643308cffdSStefano Zampini 
12658d00608fSStefano Zampini   pcbddc->rhs_change = PETSC_FALSE;
12663972b0daSStefano Zampini   /* Take into account zeroed rows -> change rhs and store solution removed */
126770c64980SStefano Zampini   if (rhs && pcbddc->eliminate_dirdofs) {
12683975b054SStefano Zampini     IS dirIS = NULL;
12693975b054SStefano Zampini 
1270a07ea27aSStefano Zampini     /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */
12719566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph, &dirIS));
12723975b054SStefano Zampini     if (dirIS) {
1273906d46d4SStefano Zampini       Mat_IS            *matis = (Mat_IS *)pc->pmat->data;
1274785d1243SStefano Zampini       PetscInt           dirsize, i, *is_indices;
12752b095fd8SStefano Zampini       PetscScalar       *array_x;
12762b095fd8SStefano Zampini       const PetscScalar *array_diagonal;
1277785d1243SStefano Zampini 
12789566063dSJacob Faibussowitsch       PetscCall(MatGetDiagonal(pc->pmat, pcis->vec1_global));
12799566063dSJacob Faibussowitsch       PetscCall(VecPointwiseDivide(pcis->vec1_global, rhs, pcis->vec1_global));
12809566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_global, pcis->vec2_N, INSERT_VALUES, SCATTER_FORWARD));
12819566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_global, pcis->vec2_N, INSERT_VALUES, SCATTER_FORWARD));
12829566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx, used_vec, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD));
12839566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx, used_vec, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD));
12849566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(dirIS, &dirsize));
12859566063dSJacob Faibussowitsch       PetscCall(VecGetArray(pcis->vec1_N, &array_x));
12869566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(pcis->vec2_N, &array_diagonal));
12879566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(dirIS, (const PetscInt **)&is_indices));
12882fa5cd67SKarl Rupp       for (i = 0; i < dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
12899566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(dirIS, (const PetscInt **)&is_indices));
12909566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(pcis->vec2_N, &array_diagonal));
12919566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(pcis->vec1_N, &array_x));
12929566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_N, used_vec, INSERT_VALUES, SCATTER_REVERSE));
12939566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_N, used_vec, INSERT_VALUES, SCATTER_REVERSE));
12948d00608fSStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
12959566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&dirIS));
12968efcfb23SStefano Zampini     }
1297a07ea27aSStefano Zampini   }
1298b76ba322SStefano Zampini 
12998efcfb23SStefano Zampini   /* remove the computed solution or the initial guess from the rhs */
13008d00608fSStefano Zampini   if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero)) {
130127b6a85dSStefano Zampini     /* save the original rhs */
130227b6a85dSStefano Zampini     if (save_rhs) {
13039566063dSJacob Faibussowitsch       PetscCall(VecSwap(rhs, pcbddc->original_rhs));
130427b6a85dSStefano Zampini       save_rhs = PETSC_FALSE;
13058d00608fSStefano Zampini     }
13068d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
13079566063dSJacob Faibussowitsch     PetscCall(VecScale(used_vec, -1.0));
13089566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(pc->mat, used_vec, pcbddc->original_rhs, rhs));
13099566063dSJacob Faibussowitsch     PetscCall(VecScale(used_vec, -1.0));
13109566063dSJacob Faibussowitsch     PetscCall(VecCopy(used_vec, pcbddc->temp_solution));
131127b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
13121baa6e33SBarry Smith     if (ksp) PetscCall(KSPSetInitialGuessNonzero(ksp, PETSC_FALSE));
13133308cffdSStefano Zampini   }
13149566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&used_vec));
1315b76ba322SStefano Zampini 
1316fc17d649SStefano Zampini   /* compute initial vector in benign space if needed
131727b6a85dSStefano Zampini      and remove non-benign solution from the rhs */
131827b6a85dSStefano Zampini   benign_correction_computed = PETSC_FALSE;
131908af2428SStefano Zampini   if (rhs && pcbddc->benign_compute_correction && (pcbddc->benign_have_null || pcbddc->benign_apply_coarse_only)) {
13201f4df5f7SStefano Zampini     /* compute u^*_h using ideas similar to those in Xuemin Tu's PhD thesis (see Section 4.8.1)
13211f4df5f7SStefano Zampini        Recursively apply BDDC in the multilevel case */
132248a46eb9SPierre Jolivet     if (!pcbddc->benign_vec) PetscCall(VecDuplicate(rhs, &pcbddc->benign_vec));
1323c69e9cc1SStefano Zampini     /* keep applying coarse solver unless we no longer have benign subdomains */
1324c69e9cc1SStefano Zampini     pcbddc->benign_apply_coarse_only = pcbddc->benign_have_null ? PETSC_TRUE : PETSC_FALSE;
132527b6a85dSStefano Zampini     if (!pcbddc->benign_skip_correction) {
13269566063dSJacob Faibussowitsch       PetscCall(PCApply_BDDC(pc, rhs, pcbddc->benign_vec));
13273bca92a6SStefano Zampini       benign_correction_computed = PETSC_TRUE;
13281baa6e33SBarry Smith       if (pcbddc->temp_solution_used) PetscCall(VecAXPY(pcbddc->temp_solution, 1.0, pcbddc->benign_vec));
13299566063dSJacob Faibussowitsch       PetscCall(VecScale(pcbddc->benign_vec, -1.0));
133027b6a85dSStefano Zampini       /* store the original rhs if not done earlier */
13311baa6e33SBarry Smith       if (save_rhs) PetscCall(VecSwap(rhs, pcbddc->original_rhs));
133227b6a85dSStefano Zampini       if (pcbddc->rhs_change) {
13339566063dSJacob Faibussowitsch         PetscCall(MatMultAdd(pc->mat, pcbddc->benign_vec, rhs, rhs));
133427b6a85dSStefano Zampini       } else {
13359566063dSJacob Faibussowitsch         PetscCall(MatMultAdd(pc->mat, pcbddc->benign_vec, pcbddc->original_rhs, rhs));
133627b6a85dSStefano Zampini       }
13370369aaf7SStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
133827b6a85dSStefano Zampini     }
133927b6a85dSStefano Zampini     pcbddc->benign_apply_coarse_only = PETSC_FALSE;
13404df7a6bfSStefano Zampini   } else {
13419566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&pcbddc->benign_vec));
13420369aaf7SStefano Zampini   }
13432d4c4fecSStefano Zampini 
13442d4c4fecSStefano Zampini   /* dbg output */
1345a198735bSStefano Zampini   if (pcbddc->dbg_flag && benign_correction_computed) {
13461f4df5f7SStefano Zampini     Vec v;
1347c69e9cc1SStefano Zampini 
13489566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_global, &v));
1349c69e9cc1SStefano Zampini     if (pcbddc->ChangeOfBasisMatrix) {
13509566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, rhs, v));
1351c69e9cc1SStefano Zampini     } else {
13529566063dSJacob Faibussowitsch       PetscCall(VecCopy(rhs, v));
1353c69e9cc1SStefano Zampini     }
13549566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, v, PETSC_TRUE));
135563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "LEVEL %" PetscInt_FMT ": is the correction benign?\n", pcbddc->current_level));
13569566063dSJacob Faibussowitsch     PetscCall(PetscScalarView(pcbddc->benign_n, pcbddc->benign_p0, pcbddc->dbg_viewer));
13579566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
13589566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&v));
13591f4df5f7SStefano Zampini   }
13600369aaf7SStefano Zampini 
13610369aaf7SStefano Zampini   /* set initial guess if using PCG */
13628ae0ca82SStefano Zampini   pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
13630369aaf7SStefano Zampini   if (x && pcbddc->use_exact_dirichlet_trick) {
13649566063dSJacob Faibussowitsch     PetscCall(VecSet(x, 0.0));
13651dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
136627b6a85dSStefano Zampini       if (benign_correction_computed) { /* we have already saved the changed rhs */
13679566063dSJacob Faibussowitsch         PetscCall(VecLockReadPop(pcis->vec1_global));
13681dd7afcfSStefano Zampini       } else {
13699566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, rhs, pcis->vec1_global));
13701dd7afcfSStefano Zampini       }
13719566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_global, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
13729566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_global, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
13731dd7afcfSStefano Zampini     } else {
13749566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D, rhs, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
13759566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D, rhs, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
13761dd7afcfSStefano Zampini     }
13779566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
13789566063dSJacob Faibussowitsch     PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D));
13799566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
13809566063dSJacob Faibussowitsch     PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D));
13811dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
13829566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_global, 0.));
13839566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, pcis->vec1_global, INSERT_VALUES, SCATTER_REVERSE));
13849566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, pcis->vec1_global, INSERT_VALUES, SCATTER_REVERSE));
13859566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcis->vec1_global, x));
13861dd7afcfSStefano Zampini     } else {
13879566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, x, INSERT_VALUES, SCATTER_REVERSE));
13889566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, x, INSERT_VALUES, SCATTER_REVERSE));
13891dd7afcfSStefano Zampini     }
13901baa6e33SBarry Smith     if (ksp) PetscCall(KSPSetInitialGuessNonzero(ksp, PETSC_TRUE));
13918ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_TRUE;
1392266e20e9SStefano Zampini   } else if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior && benign_correction_computed && pcbddc->use_exact_dirichlet_trick) {
13939566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(pcis->vec1_global));
13940369aaf7SStefano Zampini   }
13953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1396534831adSStefano Zampini }
1397906d46d4SStefano Zampini 
1398534831adSStefano Zampini /*
1399534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
1400534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
1401534831adSStefano Zampini 
1402534831adSStefano Zampini    Input Parameter:
1403966d8056SPierre Jolivet +  pc - the preconditioner context
1404534831adSStefano Zampini 
1405534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
1406534831adSStefano Zampini 
1407f1580f4eSBarry Smith    Note:
1408534831adSStefano Zampini      The interface routine PCPostSolve() is not usually called directly by
1409534831adSStefano Zampini      the user, but instead is called by KSPSolve().
1410534831adSStefano Zampini */
1411d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1412d71ae5a4SJacob Faibussowitsch {
1413534831adSStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
1414534831adSStefano Zampini 
1415534831adSStefano Zampini   PetscFunctionBegin;
14163972b0daSStefano Zampini   /* add solution removed in presolve */
14176bcfc461SStefano Zampini   if (x && pcbddc->rhs_change) {
141827b6a85dSStefano Zampini     if (pcbddc->temp_solution_used) {
14199566063dSJacob Faibussowitsch       PetscCall(VecAXPY(x, 1.0, pcbddc->temp_solution));
1420af140850Sstefano_zampini     } else if (pcbddc->benign_compute_correction && pcbddc->benign_vec) {
14219566063dSJacob Faibussowitsch       PetscCall(VecAXPY(x, -1.0, pcbddc->benign_vec));
14223425bc38SStefano Zampini     }
1423af140850Sstefano_zampini     /* restore to original state (not for FETI-DP) */
1424af140850Sstefano_zampini     if (ksp) pcbddc->temp_solution_used = PETSC_FALSE;
142527b6a85dSStefano Zampini   }
142627b6a85dSStefano Zampini 
1427266e20e9SStefano Zampini   /* restore rhs to its original state (not needed for FETI-DP) */
14288d00608fSStefano Zampini   if (rhs && pcbddc->rhs_change) {
14299566063dSJacob Faibussowitsch     PetscCall(VecSwap(rhs, pcbddc->original_rhs));
14308d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_FALSE;
1431af140850Sstefano_zampini   }
14328efcfb23SStefano Zampini   /* restore ksp guess state */
14338efcfb23SStefano Zampini   if (ksp) {
14349566063dSJacob Faibussowitsch     PetscCall(KSPSetInitialGuessNonzero(ksp, pcbddc->ksp_guess_nonzero));
14358ae0ca82SStefano Zampini     /* reset flag for exact dirichlet trick */
14368ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
1437af140850Sstefano_zampini   }
14383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1439534831adSStefano Zampini }
1440af140850Sstefano_zampini 
14410c7d97c5SJed Brown /*
14420c7d97c5SJed Brown   PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
14430c7d97c5SJed Brown   by setting data structures and options.
14440c7d97c5SJed Brown 
14450c7d97c5SJed Brown   Input Parameter:
1446*feefa0e1SJacob Faibussowitsch . pc - the preconditioner context
14470c7d97c5SJed Brown 
14480c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
14490c7d97c5SJed Brown 
1450f1580f4eSBarry Smith   Note:
14510c7d97c5SJed Brown   The interface routine PCSetUp() is not usually called directly by
14520c7d97c5SJed Brown   the user, but instead is called by PCApply() if necessary.
14530c7d97c5SJed Brown */
1454d71ae5a4SJacob Faibussowitsch PetscErrorCode PCSetUp_BDDC(PC pc)
1455d71ae5a4SJacob Faibussowitsch {
14560c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC *)pc->data;
1457c703fcc7SStefano Zampini   PCBDDCSubSchurs sub_schurs;
14585e8657edSStefano Zampini   Mat_IS         *matis;
145908122e43SStefano Zampini   MatNullSpace    nearnullspace;
146035509ce9Sstefano_zampini   Mat             lA;
146135509ce9Sstefano_zampini   IS              lP, zerodiag = NULL;
146291e8d312SStefano Zampini   PetscInt        nrows, ncols;
146386bfa4cfSStefano Zampini   PetscMPIInt     size;
1464c703fcc7SStefano Zampini   PetscBool       computesubschurs;
14658de1fae6SStefano Zampini   PetscBool       computeconstraintsmatrix;
14663b03f7bbSStefano Zampini   PetscBool       new_nearnullspace_provided, ismatis, rl;
1467b94d7dedSBarry Smith   PetscBool       isset, issym, isspd;
14680c7d97c5SJed Brown 
14690c7d97c5SJed Brown   PetscFunctionBegin;
14709566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATIS, &ismatis));
147128b400f6SJacob Faibussowitsch   PetscCheck(ismatis, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "PCBDDC preconditioner requires matrix of type MATIS");
14729566063dSJacob Faibussowitsch   PetscCall(MatGetSize(pc->pmat, &nrows, &ncols));
14737827d75bSBarry Smith   PetscCheck(nrows == ncols, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "PCBDDC preconditioner requires a square preconditioning matrix");
14749566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
147586bfa4cfSStefano Zampini 
14765e8657edSStefano Zampini   matis = (Mat_IS *)pc->pmat->data;
1477f4ddd8eeSStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */
14783b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
147971582508SStefano Zampini      Also, BDDC builds its own KSP for the Dirichlet problem */
14803b03f7bbSStefano Zampini   rl = pcbddc->recompute_topography;
14813b03f7bbSStefano Zampini   if (!pc->setupcalled || pc->flag == DIFFERENT_NONZERO_PATTERN) rl = PETSC_TRUE;
14821c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&rl, &pcbddc->recompute_topography, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc)));
1483c83e1ba7SStefano Zampini   if (pcbddc->recompute_topography) {
1484c83e1ba7SStefano Zampini     pcbddc->graphanalyzed    = PETSC_FALSE;
1485c83e1ba7SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1486c83e1ba7SStefano Zampini   } else {
14878de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_FALSE;
1488c83e1ba7SStefano Zampini   }
1489b087196eSStefano Zampini 
1490b087196eSStefano Zampini   /* check parameters' compatibility */
1491b7ab4a40SStefano Zampini   if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE;
1492bd2a564bSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_threshold[0] != 0.0 || pcbddc->adaptive_threshold[1] != 0.0);
149386bfa4cfSStefano Zampini   pcbddc->use_deluxe_scaling   = (PetscBool)(pcbddc->use_deluxe_scaling && size > 1);
149486bfa4cfSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_selection && size > 1);
1495bf3a8328SStefano Zampini   pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined);
1496862806e4SStefano Zampini   if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE;
1497862806e4SStefano Zampini 
14985a95e1ceSStefano Zampini   computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling);
149916909a7fSStefano Zampini 
150071582508SStefano Zampini   /* activate all connected components if the netflux has been requested */
1501bb05f991SStefano Zampini   if (pcbddc->compute_nonetflux) {
1502bb05f991SStefano Zampini     pcbddc->use_vertices = PETSC_TRUE;
1503bb05f991SStefano Zampini     pcbddc->use_edges    = PETSC_TRUE;
1504bb05f991SStefano Zampini     pcbddc->use_faces    = PETSC_TRUE;
1505bb05f991SStefano Zampini   }
1506bb05f991SStefano Zampini 
1507f4ddd8eeSStefano Zampini   /* Get stdout for dbg */
150870cf5478SStefano Zampini   if (pcbddc->dbg_flag) {
1509ad540459SPierre Jolivet     if (!pcbddc->dbg_viewer) pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc));
15109566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer));
15119566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIAddTab(pcbddc->dbg_viewer, 2 * pcbddc->current_level));
1512f4ddd8eeSStefano Zampini   }
1513f4ddd8eeSStefano Zampini 
1514c703fcc7SStefano Zampini   /* process topology information */
15159566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Topology[pcbddc->current_level], pc, 0, 0, 0));
151671582508SStefano Zampini   if (pcbddc->recompute_topography) {
15179566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeLocalTopologyInfo(pc));
15181baa6e33SBarry Smith     if (pcbddc->discretegradient) PetscCall(PCBDDCNedelecSupport(pc));
1519c703fcc7SStefano Zampini   }
15204f819b78SStefano Zampini   if (pcbddc->corner_selected) pcbddc->use_vertices = PETSC_TRUE;
1521a13144ffSStefano Zampini 
1522c703fcc7SStefano Zampini   /* change basis if requested by the user */
15235e8657edSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) {
15245e8657edSStefano Zampini     /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */
15255e8657edSStefano Zampini     pcbddc->use_change_of_basis = PETSC_FALSE;
15269566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeLocalMatrix(pc, pcbddc->user_ChangeOfBasisMatrix));
15275e8657edSStefano Zampini   } else {
15289566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcbddc->local_mat));
15299566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)matis->A));
15305e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
1531d16cbb6bSStefano Zampini   }
1532d16cbb6bSStefano Zampini 
15334f1b2e48SStefano Zampini   /*
1534c703fcc7SStefano Zampini      Compute change of basis on local pressures (aka zerodiag dofs) with the benign trick
15354f1b2e48SStefano Zampini      This should come earlier then PCISSetUp for extracting the correct subdomain matrices
15364f1b2e48SStefano Zampini   */
15379566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignShellMat(pc, PETSC_TRUE));
1538d16cbb6bSStefano Zampini   if (pcbddc->benign_saddle_point) {
15399f47a83aSStefano Zampini     PC_IS *pcis = (PC_IS *)pc->data;
15409f47a83aSStefano Zampini 
154105b28244SStefano Zampini     if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE;
15423b03f7bbSStefano Zampini     /* detect local saddle point and change the basis in pcbddc->local_mat */
15439566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignDetectSaddlePoint(pc, (PetscBool)(!pcbddc->recompute_topography), &zerodiag));
1544a3df083aSStefano Zampini     /* pop B0 mat from local mat */
15459566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignPopOrPushB0(pc, PETSC_TRUE));
15461dd7afcfSStefano Zampini     /* give pcis a hint to not reuse submatrices during PCISCreate */
15471dd7afcfSStefano Zampini     if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) {
15481dd7afcfSStefano Zampini       if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) {
15491dd7afcfSStefano Zampini         pcis->reusesubmatrices = PETSC_FALSE;
15501dd7afcfSStefano Zampini       } else {
1551a3df083aSStefano Zampini         pcis->reusesubmatrices = PETSC_TRUE;
15521dd7afcfSStefano Zampini       }
1553a3df083aSStefano Zampini     } else {
15549f47a83aSStefano Zampini       pcis->reusesubmatrices = PETSC_FALSE;
1555674ae819SStefano Zampini     }
1556a3df083aSStefano Zampini   }
155727b6a85dSStefano Zampini 
15588037d520SStefano Zampini   /* propagate relevant information */
1559b94d7dedSBarry Smith   PetscCall(MatIsSymmetricKnown(matis->A, &isset, &issym));
1560b94d7dedSBarry Smith   if (isset) PetscCall(MatSetOption(pcbddc->local_mat, MAT_SYMMETRIC, issym));
1561b94d7dedSBarry Smith   PetscCall(MatIsSPDKnown(matis->A, &isset, &isspd));
1562b94d7dedSBarry Smith   if (isset) PetscCall(MatSetOption(pcbddc->local_mat, MAT_SPD, isspd));
1563e496cd5dSStefano Zampini 
15645e8657edSStefano Zampini   /* Set up all the "iterative substructuring" common block without computing solvers */
15655e8657edSStefano Zampini   {
15665e8657edSStefano Zampini     Mat temp_mat;
15675e8657edSStefano Zampini 
15685e8657edSStefano Zampini     temp_mat = matis->A;
15695e8657edSStefano Zampini     matis->A = pcbddc->local_mat;
15709566063dSJacob Faibussowitsch     PetscCall(PCISSetUp(pc, PETSC_TRUE, PETSC_FALSE));
15715e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
15725e8657edSStefano Zampini     matis->A          = temp_mat;
15735e8657edSStefano Zampini   }
1574684f6988SStefano Zampini 
157581d14e9dSStefano Zampini   /* Analyze interface */
157664ac59b8SStefano Zampini   if (!pcbddc->graphanalyzed) {
15779566063dSJacob Faibussowitsch     PetscCall(PCBDDCAnalyzeInterface(pc));
15788de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
15790fdf79fbSJacob 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");
1580a198735bSStefano Zampini     if (pcbddc->compute_nonetflux) {
1581669cc0f4SStefano Zampini       MatNullSpace nnfnnsp;
1582669cc0f4SStefano Zampini 
158328b400f6SJacob Faibussowitsch       PetscCheck(pcbddc->divudotp, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Missing divudotp operator");
15849566063dSJacob Faibussowitsch       PetscCall(PCBDDCComputeNoNetFlux(pc->pmat, pcbddc->divudotp, pcbddc->divudotp_trans, pcbddc->divudotp_vl2l, pcbddc->mat_graph, &nnfnnsp));
158571582508SStefano Zampini       /* TODO what if a nearnullspace is already attached? */
15868037d520SStefano Zampini       if (nnfnnsp) {
15879566063dSJacob Faibussowitsch         PetscCall(MatSetNearNullSpace(pc->pmat, nnfnnsp));
15889566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceDestroy(&nnfnnsp));
1589669cc0f4SStefano Zampini       }
1590674ae819SStefano Zampini     }
15918037d520SStefano Zampini   }
15929566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Topology[pcbddc->current_level], pc, 0, 0, 0));
1593fb8d54d4SStefano Zampini 
15945408967cSStefano Zampini   /* check existence of a divergence free extension, i.e.
15955408967cSStefano Zampini      b(v_I,p_0) = 0 for all v_I (raise error if not).
15965408967cSStefano Zampini      Also, check that PCBDDCBenignGetOrSetP0 works */
159748a46eb9SPierre Jolivet   if (pcbddc->benign_saddle_point && pcbddc->dbg_flag > 1) PetscCall(PCBDDCBenignCheck(pc, zerodiag));
15989566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&zerodiag));
159906f24817SStefano Zampini 
1600b96c3477SStefano Zampini   /* Setup local dirichlet solver ksp_D and sub_schurs solvers */
160148a46eb9SPierre Jolivet   if (computesubschurs && pcbddc->recompute_topography) PetscCall(PCBDDCInitSubSchurs(pc));
16029d54b7f4SStefano Zampini   /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/
160348a46eb9SPierre Jolivet   if (!pcbddc->use_deluxe_scaling) PetscCall(PCBDDCScalingSetUp(pc));
1604c703fcc7SStefano Zampini 
1605c703fcc7SStefano Zampini   /* finish setup solvers and do adaptive selection of constraints */
1606b334f244SStefano Zampini   sub_schurs = pcbddc->sub_schurs;
1607b334f244SStefano Zampini   if (sub_schurs && sub_schurs->schur_explicit) {
16081baa6e33SBarry Smith     if (computesubschurs) PetscCall(PCBDDCSetUpSubSchurs(pc));
16099566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetUpLocalSolvers(pc, PETSC_TRUE, PETSC_FALSE));
1610d5574798SStefano Zampini   } else {
16119566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetUpLocalSolvers(pc, PETSC_TRUE, PETSC_FALSE));
16121baa6e33SBarry Smith     if (computesubschurs) PetscCall(PCBDDCSetUpSubSchurs(pc));
16132070dbb6SStefano Zampini   }
161408122e43SStefano Zampini   if (pcbddc->adaptive_selection) {
16159566063dSJacob Faibussowitsch     PetscCall(PCBDDCAdaptiveSelection(pc));
16168de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1617b7eb3628SStefano Zampini   }
1618684f6988SStefano Zampini 
1619f4ddd8eeSStefano Zampini   /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */
1620fb8d54d4SStefano Zampini   new_nearnullspace_provided = PETSC_FALSE;
16219566063dSJacob Faibussowitsch   PetscCall(MatGetNearNullSpace(pc->pmat, &nearnullspace));
1622f4ddd8eeSStefano Zampini   if (pcbddc->onearnullspace) { /* already used nearnullspace */
1623f4ddd8eeSStefano Zampini     if (!nearnullspace) {       /* near null space attached to mat has been destroyed */
1624f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1625f4ddd8eeSStefano Zampini     } else {
1626f4ddd8eeSStefano Zampini       /* determine if the two nullspaces are different (should be lightweight) */
1627f4ddd8eeSStefano Zampini       if (nearnullspace != pcbddc->onearnullspace) {
1628f4ddd8eeSStefano Zampini         new_nearnullspace_provided = PETSC_TRUE;
1629165b64e2SStefano Zampini       } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */
1630f4ddd8eeSStefano Zampini         PetscInt         i;
1631165b64e2SStefano Zampini         const Vec       *nearnullvecs;
1632165b64e2SStefano Zampini         PetscObjectState state;
1633165b64e2SStefano Zampini         PetscInt         nnsp_size;
16349566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceGetVecs(nearnullspace, NULL, &nnsp_size, &nearnullvecs));
1635f4ddd8eeSStefano Zampini         for (i = 0; i < nnsp_size; i++) {
16369566063dSJacob Faibussowitsch           PetscCall(PetscObjectStateGet((PetscObject)nearnullvecs[i], &state));
1637165b64e2SStefano Zampini           if (pcbddc->onearnullvecs_state[i] != state) {
1638f4ddd8eeSStefano Zampini             new_nearnullspace_provided = PETSC_TRUE;
1639f4ddd8eeSStefano Zampini             break;
1640f4ddd8eeSStefano Zampini           }
1641f4ddd8eeSStefano Zampini         }
1642f4ddd8eeSStefano Zampini       }
1643f4ddd8eeSStefano Zampini     }
1644f4ddd8eeSStefano Zampini   } else {
1645f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* both nearnullspaces are null */
1646f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_FALSE;
1647f4ddd8eeSStefano Zampini     } else { /* nearnullspace attached later */
1648f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1649f4ddd8eeSStefano Zampini     }
1650f4ddd8eeSStefano Zampini   }
1651f4ddd8eeSStefano Zampini 
1652f4ddd8eeSStefano Zampini   /* Setup constraints and related work vectors */
1653727cdba6SStefano Zampini   /* reset primal space flags */
16549566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_LocalWork[pcbddc->current_level], pc, 0, 0, 0));
1655f4ddd8eeSStefano Zampini   pcbddc->new_primal_space       = PETSC_FALSE;
1656727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_FALSE;
16578de1fae6SStefano Zampini   if (computeconstraintsmatrix || new_nearnullspace_provided) {
1658727cdba6SStefano Zampini     /* It also sets the primal space flags */
16599566063dSJacob Faibussowitsch     PetscCall(PCBDDCConstraintsSetUp(pc));
16609543d0ffSStefano Zampini   }
1661e7b262bdSStefano Zampini   /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */
16629566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetUpLocalWorkVectors(pc));
16635e8657edSStefano Zampini 
16645e8657edSStefano Zampini   if (pcbddc->use_change_of_basis) {
16655e8657edSStefano Zampini     PC_IS *pcis = (PC_IS *)(pc->data);
16665e8657edSStefano Zampini 
16679566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeLocalMatrix(pc, pcbddc->ChangeOfBasisMatrix));
16684f1b2e48SStefano Zampini     if (pcbddc->benign_change) {
16699566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcbddc->benign_B0));
1670c263805aSStefano Zampini       /* pop B0 from pcbddc->local_mat */
16719566063dSJacob Faibussowitsch       PetscCall(PCBDDCBenignPopOrPushB0(pc, PETSC_TRUE));
1672c263805aSStefano Zampini     }
16735e8657edSStefano Zampini     /* get submatrices */
16749566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_IB));
16759566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_BI));
16769566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_BB));
16779566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_B_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &pcis->A_BB));
16789566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_I_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &pcis->A_IB));
16799566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_B_local, pcis->is_I_local, MAT_INITIAL_MATRIX, &pcis->A_BI));
16803975b054SStefano Zampini     /* set flag in pcis to not reuse submatrices during PCISCreate */
16813975b054SStefano Zampini     pcis->reusesubmatrices = PETSC_FALSE;
16829c6a02ceSStefano Zampini   } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) {
16839566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcbddc->local_mat));
16849566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)matis->A));
16855e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
16865e8657edSStefano Zampini   }
168735509ce9Sstefano_zampini 
168835509ce9Sstefano_zampini   /* interface pressure block row for B_C */
16899566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lP", (PetscObject *)&lP));
16909566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lA", (PetscObject *)&lA));
169135509ce9Sstefano_zampini   if (lA && lP) {
169235509ce9Sstefano_zampini     PC_IS    *pcis = (PC_IS *)pc->data;
169335509ce9Sstefano_zampini     Mat       B_BI, B_BB, Bt_BI, Bt_BB;
169435509ce9Sstefano_zampini     PetscBool issym;
1695b94d7dedSBarry Smith 
16969566063dSJacob Faibussowitsch     PetscCall(MatIsSymmetric(lA, PETSC_SMALL, &issym));
16976cc1294bSstefano_zampini     if (issym) {
16989566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_I_local, MAT_INITIAL_MATRIX, &B_BI));
16999566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_B_local, MAT_INITIAL_MATRIX, &B_BB));
17009566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(B_BI, &Bt_BI));
17019566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(B_BB, &Bt_BB));
170235509ce9Sstefano_zampini     } else {
17039566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_I_local, MAT_INITIAL_MATRIX, &B_BI));
17049566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_B_local, MAT_INITIAL_MATRIX, &B_BB));
17059566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, pcis->is_I_local, lP, MAT_INITIAL_MATRIX, &Bt_BI));
17069566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, pcis->is_B_local, lP, MAT_INITIAL_MATRIX, &Bt_BB));
170735509ce9Sstefano_zampini     }
17089566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_B_BI", (PetscObject)B_BI));
17099566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_B_BB", (PetscObject)B_BB));
17109566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_Bt_BI", (PetscObject)Bt_BI));
17119566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_Bt_BB", (PetscObject)Bt_BB));
17129566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B_BI));
17139566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B_BB));
17149566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Bt_BI));
17159566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Bt_BB));
171635509ce9Sstefano_zampini   }
17179566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_LocalWork[pcbddc->current_level], pc, 0, 0, 0));
171835509ce9Sstefano_zampini 
1719b96c3477SStefano Zampini   /* SetUp coarse and local Neumann solvers */
17209566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetUpSolvers(pc));
1721b96c3477SStefano Zampini   /* SetUp Scaling operator */
17221baa6e33SBarry Smith   if (pcbddc->use_deluxe_scaling) PetscCall(PCBDDCScalingSetUp(pc));
1723c703fcc7SStefano Zampini 
17241dd7afcfSStefano Zampini   /* mark topography as done */
172556282151SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
17260369aaf7SStefano Zampini 
17271dd7afcfSStefano Zampini   /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */
17289566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignShellMat(pc, PETSC_FALSE));
17291dd7afcfSStefano Zampini 
173058a03d70SStefano Zampini   if (pcbddc->dbg_flag) {
17319566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISubtractTab(pcbddc->dbg_viewer, 2 * pcbddc->current_level));
17329566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer));
17332b510759SStefano Zampini   }
17343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17350c7d97c5SJed Brown }
17360c7d97c5SJed Brown 
17370c7d97c5SJed Brown /*
173850efa1b5SStefano Zampini    PCApply_BDDC - Applies the BDDC operator to a vector.
17390c7d97c5SJed Brown 
17400c7d97c5SJed Brown    Input Parameters:
17410f202f7eSStefano Zampini +  pc - the preconditioner context
17420f202f7eSStefano Zampini -  r - input vector (global)
17430c7d97c5SJed Brown 
17440c7d97c5SJed Brown    Output Parameter:
17450c7d97c5SJed Brown .  z - output vector (global)
17460c7d97c5SJed Brown 
17470c7d97c5SJed Brown    Application Interface Routine: PCApply()
17480c7d97c5SJed Brown  */
1749d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApply_BDDC(PC pc, Vec r, Vec z)
1750d71ae5a4SJacob Faibussowitsch {
17510c7d97c5SJed Brown   PC_IS            *pcis   = (PC_IS *)(pc->data);
17520c7d97c5SJed Brown   PC_BDDC          *pcbddc = (PC_BDDC *)(pc->data);
1753b3338236SStefano Zampini   Mat               lA     = NULL;
1754b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
17553b03a366Sstefano_zampini   const PetscScalar one   = 1.0;
17563b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
17572617d88aSStefano Zampini   const PetscScalar zero  = 0.0;
17580c7d97c5SJed Brown   /* This code is similar to that provided in nn.c for PCNN
17590c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
1760b097fa66SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */
17610c7d97c5SJed Brown 
17620c7d97c5SJed Brown   PetscFunctionBegin;
17639566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(citation, &cited));
176448a46eb9SPierre Jolivet   if (pcbddc->switch_static) PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat, &lA));
1765b3338236SStefano Zampini 
17661dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
17671dd7afcfSStefano Zampini     Vec swap;
176827b6a85dSStefano Zampini 
17699566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, r, pcbddc->work_change));
17701dd7afcfSStefano Zampini     swap                = pcbddc->work_change;
17711dd7afcfSStefano Zampini     pcbddc->work_change = r;
17721dd7afcfSStefano Zampini     r                   = swap;
17731dd7afcfSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
17749cc2a9b1Sstefano_zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) {
17759566063dSJacob Faibussowitsch       PetscCall(VecCopy(r, pcis->vec1_global));
17769566063dSJacob Faibussowitsch       PetscCall(VecLockReadPush(pcis->vec1_global));
17771dd7afcfSStefano Zampini     }
17781dd7afcfSStefano Zampini   }
177927b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
17809566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, r, PETSC_TRUE));
1781efc2fbd9SStefano Zampini   }
1782bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET && !pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
17839566063dSJacob Faibussowitsch     PetscCall(VecCopy(r, z));
17840c7d97c5SJed Brown     /* First Dirichlet solve */
17859566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
17869566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
17870c7d97c5SJed Brown     /*
17880c7d97c5SJed Brown       Assembling right hand side for BDDC operator
1789b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
1790674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
17910c7d97c5SJed Brown     */
1792b097fa66SStefano Zampini     if (n_D) {
17939566063dSJacob Faibussowitsch       PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
17949566063dSJacob Faibussowitsch       PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D));
17959566063dSJacob Faibussowitsch       PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
17969566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D));
17979566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec2_D, m_one));
179816909a7fSStefano Zampini       if (pcbddc->switch_static) {
17999566063dSJacob Faibussowitsch         PetscCall(VecSet(pcis->vec1_N, 0.));
18009566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
18019566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
180216909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
18039566063dSJacob Faibussowitsch           PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N));
180416909a7fSStefano Zampini         } else {
18059566063dSJacob Faibussowitsch           PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
18069566063dSJacob Faibussowitsch           PetscCall(MatMult(lA, pcis->vec2_N, pcis->vec1_N));
18079566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
180816909a7fSStefano Zampini         }
18099566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD));
18109566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD));
18119566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
18129566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
181316909a7fSStefano Zampini       } else {
18149566063dSJacob Faibussowitsch         PetscCall(MatMult(pcis->A_BI, pcis->vec2_D, pcis->vec1_B));
181516909a7fSStefano Zampini       }
1816b097fa66SStefano Zampini     } else {
18179566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_B, zero));
1818b097fa66SStefano Zampini     }
18199566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE));
18209566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE));
18219566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingRestriction(pc, z, pcis->vec1_B));
1822b76ba322SStefano Zampini   } else {
182348a46eb9SPierre Jolivet     if (!pcbddc->benign_apply_coarse_only) PetscCall(PCBDDCScalingRestriction(pc, r, pcis->vec1_B));
18244fee134fSStefano Zampini   }
1825bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) {
182628b400f6SJacob Faibussowitsch     PetscCheck(pcbddc->switch_static, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "You forgot to pass -pc_bddc_switch_static");
18279566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
18289566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
1829bc960bbfSJed Brown   }
1830b76ba322SStefano Zampini 
18312617d88aSStefano Zampini   /* Apply interface preconditioner
18322617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
18339566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(pc, PETSC_FALSE));
18342617d88aSStefano Zampini 
1835674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
18369566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(pc, pcis->vec1_B, z));
1837bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) {
18389566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_D, z, INSERT_VALUES, SCATTER_REVERSE));
18399566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_D, z, INSERT_VALUES, SCATTER_REVERSE));
18403ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1841bc960bbfSJed Brown   }
18423b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
18439566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
18449566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
1845b097fa66SStefano Zampini   if (n_B) {
184616909a7fSStefano Zampini     if (pcbddc->switch_static) {
18479566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
18489566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
18499566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
18509566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
185116909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
18529566063dSJacob Faibussowitsch         PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N));
185316909a7fSStefano Zampini       } else {
18549566063dSJacob Faibussowitsch         PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
18559566063dSJacob Faibussowitsch         PetscCall(MatMult(lA, pcis->vec2_N, pcis->vec1_N));
18569566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
185716909a7fSStefano Zampini       }
18589566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD));
18599566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD));
186016909a7fSStefano Zampini     } else {
18619566063dSJacob Faibussowitsch       PetscCall(MatMult(pcis->A_IB, pcis->vec1_B, pcis->vec3_D));
186216909a7fSStefano Zampini     }
186316909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
186416909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
18659566063dSJacob Faibussowitsch       PetscCall(MatMult(lA, pcis->vec1_D, pcis->vec3_D));
186616909a7fSStefano Zampini     } else {
18679566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_D, pcis->vec1_N));
18689566063dSJacob Faibussowitsch       PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N));
18699566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec2_N, pcis->vec3_D));
187016909a7fSStefano Zampini     }
1871b097fa66SStefano Zampini   }
18729566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
18739566063dSJacob Faibussowitsch   PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec3_D, pcis->vec4_D));
18749566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
18759566063dSJacob Faibussowitsch   PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec4_D));
1876efc2fbd9SStefano Zampini 
18778ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1878b097fa66SStefano Zampini     if (pcbddc->switch_static) {
18799566063dSJacob Faibussowitsch       PetscCall(VecAXPBYPCZ(pcis->vec2_D, m_one, one, m_one, pcis->vec4_D, pcis->vec1_D));
1880b097fa66SStefano Zampini     } else {
18819566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec2_D, m_one, m_one, pcis->vec4_D));
1882b097fa66SStefano Zampini     }
18839566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE));
18849566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE));
1885b097fa66SStefano Zampini   } else {
1886b097fa66SStefano Zampini     if (pcbddc->switch_static) {
18879566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec4_D, one, m_one, pcis->vec1_D));
1888b097fa66SStefano Zampini     } else {
18899566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec4_D, m_one));
1890b097fa66SStefano Zampini     }
18919566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE));
18929566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE));
1893b097fa66SStefano Zampini   }
189427b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
18951baa6e33SBarry Smith     if (pcbddc->benign_apply_coarse_only) PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n));
18969566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, z, PETSC_FALSE));
1897efc2fbd9SStefano Zampini   }
18981f4df5f7SStefano Zampini 
18991dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1900f913dca9SStefano Zampini     pcbddc->work_change = r;
19019566063dSJacob Faibussowitsch     PetscCall(VecCopy(z, pcbddc->work_change));
19029566063dSJacob Faibussowitsch     PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcbddc->work_change, z));
19031dd7afcfSStefano Zampini   }
19043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19050c7d97c5SJed Brown }
190650efa1b5SStefano Zampini 
190750efa1b5SStefano Zampini /*
190850efa1b5SStefano Zampini    PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector.
190950efa1b5SStefano Zampini 
191050efa1b5SStefano Zampini    Input Parameters:
19110f202f7eSStefano Zampini +  pc - the preconditioner context
19120f202f7eSStefano Zampini -  r - input vector (global)
191350efa1b5SStefano Zampini 
191450efa1b5SStefano Zampini    Output Parameter:
191550efa1b5SStefano Zampini .  z - output vector (global)
191650efa1b5SStefano Zampini 
191750efa1b5SStefano Zampini    Application Interface Routine: PCApplyTranspose()
191850efa1b5SStefano Zampini  */
1919d71ae5a4SJacob Faibussowitsch PetscErrorCode PCApplyTranspose_BDDC(PC pc, Vec r, Vec z)
1920d71ae5a4SJacob Faibussowitsch {
192150efa1b5SStefano Zampini   PC_IS            *pcis   = (PC_IS *)(pc->data);
192250efa1b5SStefano Zampini   PC_BDDC          *pcbddc = (PC_BDDC *)(pc->data);
1923b3338236SStefano Zampini   Mat               lA     = NULL;
1924b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
192550efa1b5SStefano Zampini   const PetscScalar one   = 1.0;
192650efa1b5SStefano Zampini   const PetscScalar m_one = -1.0;
192750efa1b5SStefano Zampini   const PetscScalar zero  = 0.0;
192850efa1b5SStefano Zampini 
192950efa1b5SStefano Zampini   PetscFunctionBegin;
19309566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(citation, &cited));
193148a46eb9SPierre Jolivet   if (pcbddc->switch_static) PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat, &lA));
19321dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
19331dd7afcfSStefano Zampini     Vec swap;
193427b6a85dSStefano Zampini 
19359566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, r, pcbddc->work_change));
19361dd7afcfSStefano Zampini     swap                = pcbddc->work_change;
19371dd7afcfSStefano Zampini     pcbddc->work_change = r;
19381dd7afcfSStefano Zampini     r                   = swap;
193927b6a85dSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
19408ae0ca82SStefano Zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->exact_dirichlet_trick_app && pcbddc->change_interior) {
19419566063dSJacob Faibussowitsch       PetscCall(VecCopy(r, pcis->vec1_global));
19429566063dSJacob Faibussowitsch       PetscCall(VecLockReadPush(pcis->vec1_global));
19431dd7afcfSStefano Zampini     }
194427b6a85dSStefano Zampini   }
194527b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
19469566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, r, PETSC_TRUE));
1947537c1cdfSStefano Zampini   }
19488ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
19499566063dSJacob Faibussowitsch     PetscCall(VecCopy(r, z));
195050efa1b5SStefano Zampini     /* First Dirichlet solve */
19519566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
19529566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
195350efa1b5SStefano Zampini     /*
195450efa1b5SStefano Zampini       Assembling right hand side for BDDC operator
1955b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
195650efa1b5SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
195750efa1b5SStefano Zampini     */
1958b097fa66SStefano Zampini     if (n_D) {
19599566063dSJacob Faibussowitsch       PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
19609566063dSJacob Faibussowitsch       PetscCall(KSPSolveTranspose(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D));
19619566063dSJacob Faibussowitsch       PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
19629566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D));
19639566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec2_D, m_one));
196416909a7fSStefano Zampini       if (pcbddc->switch_static) {
19659566063dSJacob Faibussowitsch         PetscCall(VecSet(pcis->vec1_N, 0.));
19669566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
19679566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
196816909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
19699566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N));
197016909a7fSStefano Zampini         } else {
19719566063dSJacob Faibussowitsch           PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
19729566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(lA, pcis->vec2_N, pcis->vec1_N));
19739566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
197416909a7fSStefano Zampini         }
19759566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD));
19769566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD));
19779566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
19789566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
197916909a7fSStefano Zampini       } else {
19809566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcis->A_IB, pcis->vec2_D, pcis->vec1_B));
198116909a7fSStefano Zampini       }
1982b097fa66SStefano Zampini     } else {
19839566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_B, zero));
1984b097fa66SStefano Zampini     }
19859566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE));
19869566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE));
19879566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingRestriction(pc, z, pcis->vec1_B));
198850efa1b5SStefano Zampini   } else {
19899566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingRestriction(pc, r, pcis->vec1_B));
199050efa1b5SStefano Zampini   }
199150efa1b5SStefano Zampini 
199250efa1b5SStefano Zampini   /* Apply interface preconditioner
199350efa1b5SStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
19949566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(pc, PETSC_TRUE));
199550efa1b5SStefano Zampini 
199650efa1b5SStefano Zampini   /* Apply transpose of partition of unity operator */
19979566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(pc, pcis->vec1_B, z));
199850efa1b5SStefano Zampini 
199950efa1b5SStefano Zampini   /* Second Dirichlet solve and assembling of output */
20009566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
20019566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
2002b097fa66SStefano Zampini   if (n_B) {
200316909a7fSStefano Zampini     if (pcbddc->switch_static) {
20049566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
20059566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
20069566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
20079566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
200816909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
20099566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N));
201016909a7fSStefano Zampini       } else {
20119566063dSJacob Faibussowitsch         PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
20129566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(lA, pcis->vec2_N, pcis->vec1_N));
20139566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
201416909a7fSStefano Zampini       }
20159566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD));
20169566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD));
201716909a7fSStefano Zampini     } else {
20189566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcis->A_BI, pcis->vec1_B, pcis->vec3_D));
201916909a7fSStefano Zampini     }
202016909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
202116909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
20229566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(lA, pcis->vec1_D, pcis->vec3_D));
202316909a7fSStefano Zampini     } else {
20249566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_D, pcis->vec1_N));
20259566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N));
20269566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec2_N, pcis->vec3_D));
202716909a7fSStefano Zampini     }
2028b097fa66SStefano Zampini   }
20299566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
20309566063dSJacob Faibussowitsch   PetscCall(KSPSolveTranspose(pcbddc->ksp_D, pcis->vec3_D, pcis->vec4_D));
20319566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
20329566063dSJacob Faibussowitsch   PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec4_D));
20338ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
2034b097fa66SStefano Zampini     if (pcbddc->switch_static) {
20359566063dSJacob Faibussowitsch       PetscCall(VecAXPBYPCZ(pcis->vec2_D, m_one, one, m_one, pcis->vec4_D, pcis->vec1_D));
2036b097fa66SStefano Zampini     } else {
20379566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec2_D, m_one, m_one, pcis->vec4_D));
2038b097fa66SStefano Zampini     }
20399566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE));
20409566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE));
2041b097fa66SStefano Zampini   } else {
2042b097fa66SStefano Zampini     if (pcbddc->switch_static) {
20439566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec4_D, one, m_one, pcis->vec1_D));
2044b097fa66SStefano Zampini     } else {
20459566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec4_D, m_one));
2046b097fa66SStefano Zampini     }
20479566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE));
20489566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE));
2049b097fa66SStefano Zampini   }
205027b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
20519566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, z, PETSC_FALSE));
2052537c1cdfSStefano Zampini   }
20531dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2054f913dca9SStefano Zampini     pcbddc->work_change = r;
20559566063dSJacob Faibussowitsch     PetscCall(VecCopy(z, pcbddc->work_change));
20569566063dSJacob Faibussowitsch     PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcbddc->work_change, z));
20571dd7afcfSStefano Zampini   }
20583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
205950efa1b5SStefano Zampini }
2060674ae819SStefano Zampini 
2061d71ae5a4SJacob Faibussowitsch PetscErrorCode PCReset_BDDC(PC pc)
2062d71ae5a4SJacob Faibussowitsch {
2063da1bb401SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
20649326c5c6Sstefano_zampini   PC_IS   *pcis   = (PC_IS *)pc->data;
20659326c5c6Sstefano_zampini   KSP      kspD, kspR, kspC;
2066da1bb401SStefano Zampini 
2067da1bb401SStefano Zampini   PetscFunctionBegin;
2068674ae819SStefano Zampini   /* free BDDC custom data  */
20699566063dSJacob Faibussowitsch   PetscCall(PCBDDCResetCustomization(pc));
2070674ae819SStefano Zampini   /* destroy objects related to topography */
20719566063dSJacob Faibussowitsch   PetscCall(PCBDDCResetTopography(pc));
207234a97f8cSStefano Zampini   /* destroy objects for scaling operator */
20739566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingDestroy(pc));
2074674ae819SStefano Zampini   /* free solvers stuff */
20759566063dSJacob Faibussowitsch   PetscCall(PCBDDCResetSolvers(pc));
207662a6ff1dSStefano Zampini   /* free global vectors needed in presolve */
20779566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->temp_solution));
20789566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->original_rhs));
20791dd7afcfSStefano Zampini   /* free data created by PCIS */
20809566063dSJacob Faibussowitsch   PetscCall(PCISDestroy(pc));
20819326c5c6Sstefano_zampini 
20829326c5c6Sstefano_zampini   /* restore defaults */
20839326c5c6Sstefano_zampini   kspD = pcbddc->ksp_D;
20849326c5c6Sstefano_zampini   kspR = pcbddc->ksp_R;
20859326c5c6Sstefano_zampini   kspC = pcbddc->coarse_ksp;
20869566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(pc->data, sizeof(*pcbddc)));
20879326c5c6Sstefano_zampini   pcis->n_neigh                     = -1;
20889326c5c6Sstefano_zampini   pcis->scaling_factor              = 1.0;
20899326c5c6Sstefano_zampini   pcis->reusesubmatrices            = PETSC_TRUE;
20909326c5c6Sstefano_zampini   pcbddc->use_local_adj             = PETSC_TRUE;
20919326c5c6Sstefano_zampini   pcbddc->use_vertices              = PETSC_TRUE;
20929326c5c6Sstefano_zampini   pcbddc->use_edges                 = PETSC_TRUE;
20939326c5c6Sstefano_zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
20949326c5c6Sstefano_zampini   pcbddc->vertex_size               = 1;
20959326c5c6Sstefano_zampini   pcbddc->recompute_topography      = PETSC_TRUE;
20969326c5c6Sstefano_zampini   pcbddc->coarse_size               = -1;
20979326c5c6Sstefano_zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
20989326c5c6Sstefano_zampini   pcbddc->coarsening_ratio          = 8;
20999326c5c6Sstefano_zampini   pcbddc->coarse_eqs_per_proc       = 1;
21009326c5c6Sstefano_zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
21019326c5c6Sstefano_zampini   pcbddc->nedfield                  = -1;
21029326c5c6Sstefano_zampini   pcbddc->nedglobal                 = PETSC_TRUE;
21039326c5c6Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
21049326c5c6Sstefano_zampini   pcbddc->sub_schurs_layers         = -1;
21059326c5c6Sstefano_zampini   pcbddc->ksp_D                     = kspD;
21069326c5c6Sstefano_zampini   pcbddc->ksp_R                     = kspR;
21079326c5c6Sstefano_zampini   pcbddc->coarse_ksp                = kspC;
21083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21099326c5c6Sstefano_zampini }
21109326c5c6Sstefano_zampini 
2111d71ae5a4SJacob Faibussowitsch PetscErrorCode PCDestroy_BDDC(PC pc)
2112d71ae5a4SJacob Faibussowitsch {
21139326c5c6Sstefano_zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
21149326c5c6Sstefano_zampini 
21159326c5c6Sstefano_zampini   PetscFunctionBegin;
21169566063dSJacob Faibussowitsch   PetscCall(PCReset_BDDC(pc));
21179566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcbddc->ksp_D));
21189566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcbddc->ksp_R));
21199566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcbddc->coarse_ksp));
21209566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDiscreteGradient_C", NULL));
21219566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDivergenceMat_C", NULL));
21229566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetChangeOfBasisMat_C", NULL));
21239566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesLocalIS_C", NULL));
21249566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesIS_C", NULL));
212532fe681dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesLocalIS_C", NULL));
212632fe681dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesIS_C", NULL));
21279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetCoarseningRatio_C", NULL));
21289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevel_C", NULL));
21299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetUseExactDirichlet_C", NULL));
21309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevels_C", NULL));
21319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundaries_C", NULL));
21329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundariesLocal_C", NULL));
21339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundaries_C", NULL));
21349566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundariesLocal_C", NULL));
21359566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundaries_C", NULL));
21369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundariesLocal_C", NULL));
21379566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundaries_C", NULL));
21389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundariesLocal_C", NULL));
21399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplitting_C", NULL));
21409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplittingLocal_C", NULL));
21419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", NULL));
21429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCCreateFETIDPOperators_C", NULL));
21439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetRHS_C", NULL));
21449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetSolution_C", NULL));
21459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", NULL));
21469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", NULL));
21479566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
21483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2149da1bb401SStefano Zampini }
21501e6b0712SBarry Smith 
2151d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetCoordinates_BDDC(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
2152d71ae5a4SJacob Faibussowitsch {
2153ab8c8b98SStefano Zampini   PC_BDDC    *pcbddc    = (PC_BDDC *)pc->data;
2154ab8c8b98SStefano Zampini   PCBDDCGraph mat_graph = pcbddc->mat_graph;
2155ab8c8b98SStefano Zampini 
2156ab8c8b98SStefano Zampini   PetscFunctionBegin;
21579566063dSJacob Faibussowitsch   PetscCall(PetscFree(mat_graph->coords));
21589566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nloc * dim, &mat_graph->coords));
21599566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(mat_graph->coords, coords, nloc * dim));
2160ab8c8b98SStefano Zampini   mat_graph->cnloc = nloc;
2161ab8c8b98SStefano Zampini   mat_graph->cdim  = dim;
2162ab8c8b98SStefano Zampini   mat_graph->cloc  = PETSC_FALSE;
21634f819b78SStefano Zampini   /* flg setup */
21644f819b78SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
21654f819b78SStefano Zampini   pcbddc->corner_selected      = PETSC_FALSE;
21663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2167ab8c8b98SStefano Zampini }
2168ab8c8b98SStefano Zampini 
2169d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCPreSolveChangeRHS_BDDC(PC pc, PetscBool *change)
2170d71ae5a4SJacob Faibussowitsch {
2171a06fd7f2SStefano Zampini   PetscFunctionBegin;
2172a06fd7f2SStefano Zampini   *change = PETSC_TRUE;
21733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2174a06fd7f2SStefano Zampini }
2175a06fd7f2SStefano Zampini 
2176d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
2177d71ae5a4SJacob Faibussowitsch {
2178674ae819SStefano Zampini   FETIDPMat_ctx mat_ctx;
2179266e20e9SStefano Zampini   Vec           work;
21803425bc38SStefano Zampini   PC_IS        *pcis;
21813425bc38SStefano Zampini   PC_BDDC      *pcbddc;
21820c7d97c5SJed Brown 
21833425bc38SStefano Zampini   PetscFunctionBegin;
21849566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx));
21853425bc38SStefano Zampini   pcis   = (PC_IS *)mat_ctx->pc->data;
21863425bc38SStefano Zampini   pcbddc = (PC_BDDC *)mat_ctx->pc->data;
21873425bc38SStefano Zampini 
21889566063dSJacob Faibussowitsch   PetscCall(VecSet(fetidp_flux_rhs, 0.0));
2189229984c5Sstefano_zampini   /* copy rhs since we may change it during PCPreSolve_BDDC */
219048a46eb9SPierre Jolivet   if (!pcbddc->original_rhs) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->original_rhs));
21916cc1294bSstefano_zampini   if (mat_ctx->rhs_flip) {
21929566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(pcbddc->original_rhs, standard_rhs, mat_ctx->rhs_flip));
21936cc1294bSstefano_zampini   } else {
21949566063dSJacob Faibussowitsch     PetscCall(VecCopy(standard_rhs, pcbddc->original_rhs));
21956cc1294bSstefano_zampini   }
2196af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
2197229984c5Sstefano_zampini     /* interface pressure rhs */
21989566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->g2g_p, fetidp_flux_rhs, pcbddc->original_rhs, INSERT_VALUES, SCATTER_REVERSE));
21999566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->g2g_p, fetidp_flux_rhs, pcbddc->original_rhs, INSERT_VALUES, SCATTER_REVERSE));
22009566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->g2g_p, standard_rhs, fetidp_flux_rhs, INSERT_VALUES, SCATTER_FORWARD));
22019566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->g2g_p, standard_rhs, fetidp_flux_rhs, INSERT_VALUES, SCATTER_FORWARD));
220248a46eb9SPierre Jolivet     if (!mat_ctx->rhs_flip) PetscCall(VecScale(fetidp_flux_rhs, -1.));
22036cc1294bSstefano_zampini   }
2204c08af4c6SStefano Zampini   /*
2205c08af4c6SStefano Zampini      change of basis for physical rhs if needed
2206c08af4c6SStefano Zampini      It also changes the rhs in case of dirichlet boundaries
2207c08af4c6SStefano Zampini   */
22089566063dSJacob Faibussowitsch   PetscCall(PCPreSolve_BDDC(mat_ctx->pc, NULL, pcbddc->original_rhs, NULL));
2209fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
22109566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, pcbddc->original_rhs, pcbddc->work_change));
22113738a8e6SStefano Zampini     work = pcbddc->work_change;
2212fc17d649SStefano Zampini   } else {
22133738a8e6SStefano Zampini     work = pcbddc->original_rhs;
2214fc17d649SStefano Zampini   }
22153425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
22169566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_D, work, mat_ctx->temp_solution_D, INSERT_VALUES, SCATTER_FORWARD));
22179566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_D, work, mat_ctx->temp_solution_D, INSERT_VALUES, SCATTER_FORWARD));
2218fb223d50SStefano Zampini   /* scale rhs since it should be unassembled */
2219fb223d50SStefano Zampini   /* TODO use counter scaling? (also below) */
22209566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD));
22219566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD));
2222674ae819SStefano Zampini   /* Apply partition of unity */
22239566063dSJacob Faibussowitsch   PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B, pcis->D, mat_ctx->temp_solution_B));
22249566063dSJacob Faibussowitsch   /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */
22258eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
22263425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
22279566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0));
22289566063dSJacob Faibussowitsch     PetscCall(KSPSolve(pcbddc->ksp_D, mat_ctx->temp_solution_D, pcis->vec1_D));
22299566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0));
2230c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
22319566063dSJacob Faibussowitsch     PetscCall(MatMult(pcis->A_BI, pcis->vec1_D, pcis->vec1_B));
22329566063dSJacob Faibussowitsch     PetscCall(VecAXPY(mat_ctx->temp_solution_B, -1.0, pcis->vec1_B));
22339566063dSJacob Faibussowitsch     PetscCall(VecSet(work, 0.0));
22349566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, mat_ctx->temp_solution_B, work, ADD_VALUES, SCATTER_REVERSE));
22359566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, mat_ctx->temp_solution_B, work, ADD_VALUES, SCATTER_REVERSE));
22369566063dSJacob Faibussowitsch     /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */
22379566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD));
22389566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD));
22399566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B, pcis->D, mat_ctx->temp_solution_B));
22403425bc38SStefano Zampini   }
22413425bc38SStefano Zampini   /* BDDC rhs */
22429566063dSJacob Faibussowitsch   PetscCall(VecCopy(mat_ctx->temp_solution_B, pcis->vec1_B));
22431baa6e33SBarry Smith   if (pcbddc->switch_static) PetscCall(VecCopy(mat_ctx->temp_solution_D, pcis->vec1_D));
22443425bc38SStefano Zampini   /* apply BDDC */
22459566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n));
22469566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc, PETSC_FALSE));
22479566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n));
2248229984c5Sstefano_zampini 
22493425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
22509566063dSJacob Faibussowitsch   PetscCall(MatMult(mat_ctx->B_delta, pcis->vec1_B, mat_ctx->lambda_local));
22519566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(mat_ctx->l2g_lambda, mat_ctx->lambda_local, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD));
22529566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(mat_ctx->l2g_lambda, mat_ctx->lambda_local, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD));
2253229984c5Sstefano_zampini   /* Add contribution to interface pressures */
2254229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
22559566063dSJacob Faibussowitsch     PetscCall(MatMult(mat_ctx->B_BB, pcis->vec1_B, mat_ctx->vP));
22561baa6e33SBarry Smith     if (pcbddc->switch_static) PetscCall(MatMultAdd(mat_ctx->B_BI, pcis->vec1_D, mat_ctx->vP, mat_ctx->vP));
22579566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->l2g_p, mat_ctx->vP, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD));
22589566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->l2g_p, mat_ctx->vP, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD));
2259229984c5Sstefano_zampini   }
22603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22613425bc38SStefano Zampini }
22621e6b0712SBarry Smith 
22633425bc38SStefano Zampini /*@
226498ad52f2SBarry Smith   PCBDDCMatFETIDPGetRHS - Compute the right-hand side for a FETI-DP linear system using the physical right-hand side
22653425bc38SStefano Zampini 
22663425bc38SStefano Zampini   Collective
22673425bc38SStefano Zampini 
22683425bc38SStefano Zampini   Input Parameters:
2269f1580f4eSBarry Smith + fetidp_mat   - the FETI-DP matrix object obtained by a call to `PCBDDCCreateFETIDPOperators()`
22700f202f7eSStefano Zampini - standard_rhs - the right-hand side of the original linear system
22713425bc38SStefano Zampini 
2272f1580f4eSBarry Smith   Output Parameter:
22730f202f7eSStefano Zampini . fetidp_flux_rhs - the right-hand side for the FETI-DP linear system
22743425bc38SStefano Zampini 
22753425bc38SStefano Zampini   Level: developer
22763425bc38SStefano Zampini 
227716b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCCreateFETIDPOperators()`, `PCBDDCMatFETIDPGetSolution()`
22783425bc38SStefano Zampini @*/
2279d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
2280d71ae5a4SJacob Faibussowitsch {
2281674ae819SStefano Zampini   FETIDPMat_ctx mat_ctx;
22823425bc38SStefano Zampini 
22833425bc38SStefano Zampini   PetscFunctionBegin;
2284266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat, MAT_CLASSID, 1);
2285266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_rhs, VEC_CLASSID, 2);
2286266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_rhs, VEC_CLASSID, 3);
22879566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx));
2288cac4c232SBarry Smith   PetscUseMethod(mat_ctx->pc, "PCBDDCMatFETIDPGetRHS_C", (Mat, Vec, Vec), (fetidp_mat, standard_rhs, fetidp_flux_rhs));
22893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22903425bc38SStefano Zampini }
22911e6b0712SBarry Smith 
2292d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
2293d71ae5a4SJacob Faibussowitsch {
2294674ae819SStefano Zampini   FETIDPMat_ctx mat_ctx;
22953425bc38SStefano Zampini   PC_IS        *pcis;
22963425bc38SStefano Zampini   PC_BDDC      *pcbddc;
2297229984c5Sstefano_zampini   Vec           work;
22983425bc38SStefano Zampini 
22993425bc38SStefano Zampini   PetscFunctionBegin;
23009566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx));
23013425bc38SStefano Zampini   pcis   = (PC_IS *)mat_ctx->pc->data;
23023425bc38SStefano Zampini   pcbddc = (PC_BDDC *)mat_ctx->pc->data;
23033425bc38SStefano Zampini 
23043425bc38SStefano Zampini   /* apply B_delta^T */
23059566063dSJacob Faibussowitsch   PetscCall(VecSet(pcis->vec1_B, 0.));
23069566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(mat_ctx->l2g_lambda, fetidp_flux_sol, mat_ctx->lambda_local, INSERT_VALUES, SCATTER_REVERSE));
23079566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(mat_ctx->l2g_lambda, fetidp_flux_sol, mat_ctx->lambda_local, INSERT_VALUES, SCATTER_REVERSE));
23089566063dSJacob Faibussowitsch   PetscCall(MatMultTranspose(mat_ctx->B_delta, mat_ctx->lambda_local, pcis->vec1_B));
2309229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
23109566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->l2g_p, fetidp_flux_sol, mat_ctx->vP, INSERT_VALUES, SCATTER_REVERSE));
23119566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->l2g_p, fetidp_flux_sol, mat_ctx->vP, INSERT_VALUES, SCATTER_REVERSE));
23129566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(mat_ctx->Bt_BB, mat_ctx->vP, pcis->vec1_B, pcis->vec1_B));
2313229984c5Sstefano_zampini   }
2314229984c5Sstefano_zampini 
23153425bc38SStefano Zampini   /* compute rhs for BDDC application */
23169566063dSJacob Faibussowitsch   PetscCall(VecAYPX(pcis->vec1_B, -1.0, mat_ctx->temp_solution_B));
23178eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
23189566063dSJacob Faibussowitsch     PetscCall(VecCopy(mat_ctx->temp_solution_D, pcis->vec1_D));
2319229984c5Sstefano_zampini     if (mat_ctx->l2g_p) {
23209566063dSJacob Faibussowitsch       PetscCall(VecScale(mat_ctx->vP, -1.));
23219566063dSJacob Faibussowitsch       PetscCall(MatMultAdd(mat_ctx->Bt_BI, mat_ctx->vP, pcis->vec1_D, pcis->vec1_D));
23223425bc38SStefano Zampini     }
2323229984c5Sstefano_zampini   }
2324229984c5Sstefano_zampini 
23253425bc38SStefano Zampini   /* apply BDDC */
23269566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n));
23279566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc, PETSC_FALSE));
2328229984c5Sstefano_zampini 
2329229984c5Sstefano_zampini   /* put values into global vector */
2330af140850Sstefano_zampini   if (pcbddc->ChangeOfBasisMatrix) work = pcbddc->work_change;
2331af140850Sstefano_zampini   else work = standard_sol;
23329566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, work, INSERT_VALUES, SCATTER_REVERSE));
23339566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, work, INSERT_VALUES, SCATTER_REVERSE));
23348eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
23353425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
23369566063dSJacob Faibussowitsch     PetscCall(MatMult(pcis->A_IB, pcis->vec1_B, pcis->vec1_D));
23379566063dSJacob Faibussowitsch     PetscCall(VecAYPX(pcis->vec1_D, -1.0, mat_ctx->temp_solution_D));
23389566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0));
23399566063dSJacob Faibussowitsch     PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec1_D));
23409566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0));
2341c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
23423425bc38SStefano Zampini   }
2343229984c5Sstefano_zampini 
23449566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_D, work, INSERT_VALUES, SCATTER_REVERSE));
23459566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_D, work, INSERT_VALUES, SCATTER_REVERSE));
2346266e20e9SStefano Zampini   /* add p0 solution to final solution */
23479566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignGetOrSetP0(mat_ctx->pc, work, PETSC_FALSE));
23481baa6e33SBarry Smith   if (pcbddc->ChangeOfBasisMatrix) PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, work, standard_sol));
23499566063dSJacob Faibussowitsch   PetscCall(PCPostSolve_BDDC(mat_ctx->pc, NULL, NULL, standard_sol));
2350af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
23519566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->g2g_p, fetidp_flux_sol, standard_sol, INSERT_VALUES, SCATTER_REVERSE));
23529566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->g2g_p, fetidp_flux_sol, standard_sol, INSERT_VALUES, SCATTER_REVERSE));
2353229984c5Sstefano_zampini   }
23543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23553425bc38SStefano Zampini }
23561e6b0712SBarry Smith 
2357d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_BDDCIPC(PC pc, PetscViewer viewer)
2358d71ae5a4SJacob Faibussowitsch {
23595a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
23605a1e936bSStefano Zampini   PetscBool   isascii;
23615a1e936bSStefano Zampini 
23625a1e936bSStefano Zampini   PetscFunctionBegin;
23639566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
23649566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
236548a46eb9SPierre Jolivet   if (isascii) PetscCall(PetscViewerASCIIPrintf(viewer, "BDDC interface preconditioner\n"));
23669566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushTab(viewer));
23679566063dSJacob Faibussowitsch   PetscCall(PCView(bddcipc_ctx->bddc, viewer));
23689566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopTab(viewer));
23693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23705a1e936bSStefano Zampini }
23715a1e936bSStefano Zampini 
2372d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetUp_BDDCIPC(PC pc)
2373d71ae5a4SJacob Faibussowitsch {
23745a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
23755a1e936bSStefano Zampini   PetscBool   isbddc;
23765a1e936bSStefano Zampini   Vec         vv;
23775a1e936bSStefano Zampini   IS          is;
23785a1e936bSStefano Zampini   PC_IS      *pcis;
23795a1e936bSStefano Zampini 
23805a1e936bSStefano Zampini   PetscFunctionBegin;
23819566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
23829566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)bddcipc_ctx->bddc, PCBDDC, &isbddc));
238328b400f6SJacob Faibussowitsch   PetscCheck(isbddc, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Invalid type %s. Must be of type bddc", ((PetscObject)bddcipc_ctx->bddc)->type_name);
23849566063dSJacob Faibussowitsch   PetscCall(PCSetUp(bddcipc_ctx->bddc));
23855a1e936bSStefano Zampini 
23865a1e936bSStefano Zampini   /* create interface scatter */
23875a1e936bSStefano Zampini   pcis = (PC_IS *)(bddcipc_ctx->bddc->data);
23889566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l));
23899566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(pc->pmat, &vv, NULL));
23909566063dSJacob Faibussowitsch   PetscCall(ISRenumber(pcis->is_B_global, NULL, NULL, &is));
23919566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(vv, is, pcis->vec1_B, NULL, &bddcipc_ctx->g2l));
23929566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
23939566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&vv));
23943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23955a1e936bSStefano Zampini }
23965a1e936bSStefano Zampini 
2397d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_BDDCIPC(PC pc, Vec r, Vec x)
2398d71ae5a4SJacob Faibussowitsch {
23995a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
24005a1e936bSStefano Zampini   PC_IS      *pcis;
24015a1e936bSStefano Zampini   VecScatter  tmps;
24025a1e936bSStefano Zampini 
24035a1e936bSStefano Zampini   PetscFunctionBegin;
24049566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
24055a1e936bSStefano Zampini   pcis              = (PC_IS *)(bddcipc_ctx->bddc->data);
24065a1e936bSStefano Zampini   tmps              = pcis->global_to_B;
24075a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
24089566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc, r, pcis->vec1_B));
24099566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc, PETSC_FALSE));
24109566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc, pcis->vec1_B, x));
24115a1e936bSStefano Zampini   pcis->global_to_B = tmps;
24123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24135a1e936bSStefano Zampini }
24145a1e936bSStefano Zampini 
2415d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_BDDCIPC(PC pc, Vec r, Vec x)
2416d71ae5a4SJacob Faibussowitsch {
24175a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
24185a1e936bSStefano Zampini   PC_IS      *pcis;
24195a1e936bSStefano Zampini   VecScatter  tmps;
24205a1e936bSStefano Zampini 
24215a1e936bSStefano Zampini   PetscFunctionBegin;
24229566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
24235a1e936bSStefano Zampini   pcis              = (PC_IS *)(bddcipc_ctx->bddc->data);
24245a1e936bSStefano Zampini   tmps              = pcis->global_to_B;
24255a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
24269566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc, r, pcis->vec1_B));
24279566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc, PETSC_TRUE));
24289566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc, pcis->vec1_B, x));
24295a1e936bSStefano Zampini   pcis->global_to_B = tmps;
24303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24315a1e936bSStefano Zampini }
24325a1e936bSStefano Zampini 
2433d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_BDDCIPC(PC pc)
2434d71ae5a4SJacob Faibussowitsch {
24355a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
24365a1e936bSStefano Zampini 
24375a1e936bSStefano Zampini   PetscFunctionBegin;
24389566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
24399566063dSJacob Faibussowitsch   PetscCall(PCDestroy(&bddcipc_ctx->bddc));
24409566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l));
24419566063dSJacob Faibussowitsch   PetscCall(PetscFree(bddcipc_ctx));
24423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24435a1e936bSStefano Zampini }
24445a1e936bSStefano Zampini 
24453425bc38SStefano Zampini /*@
24460f202f7eSStefano Zampini   PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system
24473425bc38SStefano Zampini 
24483425bc38SStefano Zampini   Collective
24493425bc38SStefano Zampini 
24503425bc38SStefano Zampini   Input Parameters:
245120f4b53cSBarry Smith + fetidp_mat      - the FETI-DP matrix obtained by a call to `PCBDDCCreateFETIDPOperators()`
2452f1580f4eSBarry Smith - fetidp_flux_sol - the solution of the FETI-DP linear system`
24533425bc38SStefano Zampini 
2454f1580f4eSBarry Smith   Output Parameter:
24550f202f7eSStefano Zampini . standard_sol - the solution defined on the physical domain
24563425bc38SStefano Zampini 
24573425bc38SStefano Zampini   Level: developer
24583425bc38SStefano Zampini 
245916b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCCreateFETIDPOperators()`, `PCBDDCMatFETIDPGetRHS()`
24603425bc38SStefano Zampini @*/
2461d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
2462d71ae5a4SJacob Faibussowitsch {
2463674ae819SStefano Zampini   FETIDPMat_ctx mat_ctx;
24643425bc38SStefano Zampini 
24653425bc38SStefano Zampini   PetscFunctionBegin;
2466266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat, MAT_CLASSID, 1);
2467266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_sol, VEC_CLASSID, 2);
2468266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_sol, VEC_CLASSID, 3);
24699566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx));
2470cac4c232SBarry Smith   PetscUseMethod(mat_ctx->pc, "PCBDDCMatFETIDPGetSolution_C", (Mat, Vec, Vec), (fetidp_mat, fetidp_flux_sol, standard_sol));
24713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24723425bc38SStefano Zampini }
24731e6b0712SBarry Smith 
2474d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc)
2475d71ae5a4SJacob Faibussowitsch {
2476674ae819SStefano Zampini   FETIDPMat_ctx fetidpmat_ctx;
24773425bc38SStefano Zampini   Mat           newmat;
2478674ae819SStefano Zampini   FETIDPPC_ctx  fetidppc_ctx;
24793425bc38SStefano Zampini   PC            newpc;
2480ce94432eSBarry Smith   MPI_Comm      comm;
24813425bc38SStefano Zampini 
24823425bc38SStefano Zampini   PetscFunctionBegin;
24839566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)pc, &comm));
248415579a77SStefano Zampini   /* FETI-DP matrix */
24859566063dSJacob Faibussowitsch   PetscCall(PCBDDCCreateFETIDPMatContext(pc, &fetidpmat_ctx));
24861720468bSStefano Zampini   fetidpmat_ctx->fully_redundant = fully_redundant;
24879566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetupFETIDPMatContext(fetidpmat_ctx));
24889566063dSJacob Faibussowitsch   PetscCall(MatCreateShell(comm, fetidpmat_ctx->n, fetidpmat_ctx->n, fetidpmat_ctx->N, fetidpmat_ctx->N, fetidpmat_ctx, &newmat));
24899566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)newmat, !fetidpmat_ctx->l2g_lambda_only ? "F" : "G"));
24909566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(newmat, MATOP_MULT, (void (*)(void))FETIDPMatMult));
24919566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(newmat, MATOP_MULT_TRANSPOSE, (void (*)(void))FETIDPMatMultTranspose));
24929566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(newmat, MATOP_DESTROY, (void (*)(void))PCBDDCDestroyFETIDPMat));
249315579a77SStefano Zampini   /* propagate MatOptions */
249415579a77SStefano Zampini   {
249515579a77SStefano Zampini     PC_BDDC  *pcbddc = (PC_BDDC *)fetidpmat_ctx->pc->data;
2496b94d7dedSBarry Smith     PetscBool isset, issym;
249715579a77SStefano Zampini 
2498b94d7dedSBarry Smith     PetscCall(MatIsSymmetricKnown(pc->mat, &isset, &issym));
2499b94d7dedSBarry Smith     if ((isset && issym) || pcbddc->symmetric_primal) PetscCall(MatSetOption(newmat, MAT_SYMMETRIC, PETSC_TRUE));
250015579a77SStefano Zampini   }
25019566063dSJacob Faibussowitsch   PetscCall(MatSetOptionsPrefix(newmat, prefix));
25029566063dSJacob Faibussowitsch   PetscCall(MatAppendOptionsPrefix(newmat, "fetidp_"));
25039566063dSJacob Faibussowitsch   PetscCall(MatSetUp(newmat));
250415579a77SStefano Zampini   /* FETI-DP preconditioner */
25059566063dSJacob Faibussowitsch   PetscCall(PCBDDCCreateFETIDPPCContext(pc, &fetidppc_ctx));
25069566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetupFETIDPPCContext(newmat, fetidppc_ctx));
25079566063dSJacob Faibussowitsch   PetscCall(PCCreate(comm, &newpc));
25089566063dSJacob Faibussowitsch   PetscCall(PCSetOperators(newpc, newmat, newmat));
25099566063dSJacob Faibussowitsch   PetscCall(PCSetOptionsPrefix(newpc, prefix));
25109566063dSJacob Faibussowitsch   PetscCall(PCAppendOptionsPrefix(newpc, "fetidp_"));
25119566063dSJacob Faibussowitsch   PetscCall(PCSetErrorIfFailure(newpc, pc->erroriffailure));
251215579a77SStefano Zampini   if (!fetidpmat_ctx->l2g_lambda_only) { /* standard FETI-DP */
25139566063dSJacob Faibussowitsch     PetscCall(PCSetType(newpc, PCSHELL));
25149566063dSJacob Faibussowitsch     PetscCall(PCShellSetName(newpc, "FETI-DP multipliers"));
25159566063dSJacob Faibussowitsch     PetscCall(PCShellSetContext(newpc, fetidppc_ctx));
25169566063dSJacob Faibussowitsch     PetscCall(PCShellSetApply(newpc, FETIDPPCApply));
25179566063dSJacob Faibussowitsch     PetscCall(PCShellSetApplyTranspose(newpc, FETIDPPCApplyTranspose));
25189566063dSJacob Faibussowitsch     PetscCall(PCShellSetView(newpc, FETIDPPCView));
25199566063dSJacob Faibussowitsch     PetscCall(PCShellSetDestroy(newpc, PCBDDCDestroyFETIDPPC));
25205a1e936bSStefano Zampini   } else { /* saddle-point FETI-DP */
25215a1e936bSStefano Zampini     Mat       M;
25225a1e936bSStefano Zampini     PetscInt  psize;
25235a1e936bSStefano Zampini     PetscBool fake = PETSC_FALSE, isfieldsplit;
2524e1214c54Sstefano_zampini 
25259566063dSJacob Faibussowitsch     PetscCall(ISViewFromOptions(fetidpmat_ctx->lagrange, NULL, "-lag_view"));
25269566063dSJacob Faibussowitsch     PetscCall(ISViewFromOptions(fetidpmat_ctx->pressure, NULL, "-press_view"));
25279566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_PPmat", (PetscObject *)&M));
25289566063dSJacob Faibussowitsch     PetscCall(PCSetType(newpc, PCFIELDSPLIT));
25299566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetIS(newpc, "lag", fetidpmat_ctx->lagrange));
25309566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetIS(newpc, "p", fetidpmat_ctx->pressure));
25319566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetType(newpc, PC_COMPOSITE_SCHUR));
25329566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetSchurFactType(newpc, PC_FIELDSPLIT_SCHUR_FACT_DIAG));
25339566063dSJacob Faibussowitsch     PetscCall(ISGetSize(fetidpmat_ctx->pressure, &psize));
25345a1e936bSStefano Zampini     if (psize != M->rmap->N) {
25355a1e936bSStefano Zampini       Mat      M2;
25365a1e936bSStefano Zampini       PetscInt lpsize;
25375a1e936bSStefano Zampini 
25385a1e936bSStefano Zampini       fake = PETSC_TRUE;
25399566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(fetidpmat_ctx->pressure, &lpsize));
25409566063dSJacob Faibussowitsch       PetscCall(MatCreate(comm, &M2));
25419566063dSJacob Faibussowitsch       PetscCall(MatSetType(M2, MATAIJ));
25429566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(M2, lpsize, lpsize, psize, psize));
25439566063dSJacob Faibussowitsch       PetscCall(MatSetUp(M2));
25449566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(M2, MAT_FINAL_ASSEMBLY));
25459566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(M2, MAT_FINAL_ASSEMBLY));
25469566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSetSchurPre(newpc, PC_FIELDSPLIT_SCHUR_PRE_USER, M2));
25479566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&M2));
25485a1e936bSStefano Zampini     } else {
25499566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSetSchurPre(newpc, PC_FIELDSPLIT_SCHUR_PRE_USER, M));
25505a1e936bSStefano Zampini     }
25519566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetSchurScale(newpc, 1.0));
255215579a77SStefano Zampini 
255315579a77SStefano Zampini     /* we need to setfromoptions and setup here to access the blocks */
25549566063dSJacob Faibussowitsch     PetscCall(PCSetFromOptions(newpc));
25559566063dSJacob Faibussowitsch     PetscCall(PCSetUp(newpc));
2556e1214c54Sstefano_zampini 
25575a1e936bSStefano Zampini     /* user may have changed the type (e.g. -fetidp_pc_type none) */
25589566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)newpc, PCFIELDSPLIT, &isfieldsplit));
25595a1e936bSStefano Zampini     if (isfieldsplit) {
25605a1e936bSStefano Zampini       KSP      *ksps;
25615a1e936bSStefano Zampini       PC        ppc, lagpc;
25625a1e936bSStefano Zampini       PetscInt  nn;
2563064a4176SStefano Zampini       PetscBool ismatis, matisok = PETSC_FALSE, check = PETSC_FALSE;
25645a1e936bSStefano Zampini 
2565e1214c54Sstefano_zampini       /* set the solver for the (0,0) block */
25669566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSchurGetSubKSP(newpc, &nn, &ksps));
25675a1e936bSStefano Zampini       if (!nn) { /* not of type PC_COMPOSITE_SCHUR */
25689566063dSJacob Faibussowitsch         PetscCall(PCFieldSplitGetSubKSP(newpc, &nn, &ksps));
25695a1e936bSStefano Zampini         if (!fake) { /* pass pmat to the pressure solver */
25705a1e936bSStefano Zampini           Mat F;
25715a1e936bSStefano Zampini 
25729566063dSJacob Faibussowitsch           PetscCall(KSPGetOperators(ksps[1], &F, NULL));
25739566063dSJacob Faibussowitsch           PetscCall(KSPSetOperators(ksps[1], F, M));
25745a1e936bSStefano Zampini         }
25755a1e936bSStefano Zampini       } else {
2576b94d7dedSBarry Smith         PetscBool issym, isset;
25775a1e936bSStefano Zampini         Mat       S;
25785a1e936bSStefano Zampini 
25799566063dSJacob Faibussowitsch         PetscCall(PCFieldSplitSchurGetS(newpc, &S));
2580b94d7dedSBarry Smith         PetscCall(MatIsSymmetricKnown(newmat, &isset, &issym));
2581b94d7dedSBarry Smith         if (isset) PetscCall(MatSetOption(S, MAT_SYMMETRIC, issym));
25825a1e936bSStefano Zampini       }
25839566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksps[0], &lagpc));
25849566063dSJacob Faibussowitsch       PetscCall(PCSetType(lagpc, PCSHELL));
25859566063dSJacob Faibussowitsch       PetscCall(PCShellSetName(lagpc, "FETI-DP multipliers"));
25869566063dSJacob Faibussowitsch       PetscCall(PCShellSetContext(lagpc, fetidppc_ctx));
25879566063dSJacob Faibussowitsch       PetscCall(PCShellSetApply(lagpc, FETIDPPCApply));
25889566063dSJacob Faibussowitsch       PetscCall(PCShellSetApplyTranspose(lagpc, FETIDPPCApplyTranspose));
25899566063dSJacob Faibussowitsch       PetscCall(PCShellSetView(lagpc, FETIDPPCView));
25909566063dSJacob Faibussowitsch       PetscCall(PCShellSetDestroy(lagpc, PCBDDCDestroyFETIDPPC));
25915a1e936bSStefano Zampini 
25925a1e936bSStefano Zampini       /* Olof's idea: interface Schur complement preconditioner for the mass matrix */
25939566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksps[1], &ppc));
25945a1e936bSStefano Zampini       if (fake) {
25955a1e936bSStefano Zampini         BDDCIPC_ctx    bddcipc_ctx;
2596ff11fd76SStefano Zampini         PetscContainer c;
25975a1e936bSStefano Zampini 
25985a1e936bSStefano Zampini         matisok = PETSC_TRUE;
25995a1e936bSStefano Zampini 
26005a1e936bSStefano Zampini         /* create inner BDDC solver */
26019566063dSJacob Faibussowitsch         PetscCall(PetscNew(&bddcipc_ctx));
26029566063dSJacob Faibussowitsch         PetscCall(PCCreate(comm, &bddcipc_ctx->bddc));
26039566063dSJacob Faibussowitsch         PetscCall(PCSetType(bddcipc_ctx->bddc, PCBDDC));
26049566063dSJacob Faibussowitsch         PetscCall(PCSetOperators(bddcipc_ctx->bddc, M, M));
26059566063dSJacob Faibussowitsch         PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_pCSR", (PetscObject *)&c));
26069566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)M, MATIS, &ismatis));
2607ff11fd76SStefano Zampini         if (c && ismatis) {
2608ff11fd76SStefano Zampini           Mat       lM;
2609ff11fd76SStefano Zampini           PetscInt *csr, n;
2610ff11fd76SStefano Zampini 
26119566063dSJacob Faibussowitsch           PetscCall(MatISGetLocalMat(M, &lM));
26129566063dSJacob Faibussowitsch           PetscCall(MatGetSize(lM, &n, NULL));
26139566063dSJacob Faibussowitsch           PetscCall(PetscContainerGetPointer(c, (void **)&csr));
26149566063dSJacob Faibussowitsch           PetscCall(PCBDDCSetLocalAdjacencyGraph(bddcipc_ctx->bddc, n, csr, csr + (n + 1), PETSC_COPY_VALUES));
26159566063dSJacob Faibussowitsch           PetscCall(MatISRestoreLocalMat(M, &lM));
2616ff11fd76SStefano Zampini         }
26179566063dSJacob Faibussowitsch         PetscCall(PCSetOptionsPrefix(bddcipc_ctx->bddc, ((PetscObject)ksps[1])->prefix));
26189566063dSJacob Faibussowitsch         PetscCall(PCSetErrorIfFailure(bddcipc_ctx->bddc, pc->erroriffailure));
26199566063dSJacob Faibussowitsch         PetscCall(PCSetFromOptions(bddcipc_ctx->bddc));
26205a1e936bSStefano Zampini 
26215a1e936bSStefano Zampini         /* wrap the interface application */
26229566063dSJacob Faibussowitsch         PetscCall(PCSetType(ppc, PCSHELL));
26239566063dSJacob Faibussowitsch         PetscCall(PCShellSetName(ppc, "FETI-DP pressure"));
26249566063dSJacob Faibussowitsch         PetscCall(PCShellSetContext(ppc, bddcipc_ctx));
26259566063dSJacob Faibussowitsch         PetscCall(PCShellSetSetUp(ppc, PCSetUp_BDDCIPC));
26269566063dSJacob Faibussowitsch         PetscCall(PCShellSetApply(ppc, PCApply_BDDCIPC));
26279566063dSJacob Faibussowitsch         PetscCall(PCShellSetApplyTranspose(ppc, PCApplyTranspose_BDDCIPC));
26289566063dSJacob Faibussowitsch         PetscCall(PCShellSetView(ppc, PCView_BDDCIPC));
26299566063dSJacob Faibussowitsch         PetscCall(PCShellSetDestroy(ppc, PCDestroy_BDDCIPC));
26305a1e936bSStefano Zampini       }
26315a1e936bSStefano Zampini 
26325a1e936bSStefano Zampini       /* determine if we need to assemble M to construct a preconditioner */
26335a1e936bSStefano Zampini       if (!matisok) {
26349566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)M, MATIS, &ismatis));
26359566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompareAny((PetscObject)ppc, &matisok, PCBDDC, PCJACOBI, PCNONE, PCMG, ""));
263648a46eb9SPierre Jolivet         if (ismatis && !matisok) PetscCall(MatConvert(M, MATAIJ, MAT_INPLACE_MATRIX, &M));
26375a1e936bSStefano Zampini       }
2638064a4176SStefano Zampini 
2639064a4176SStefano Zampini       /* run the subproblems to check convergence */
26409566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)newmat)->prefix, "-check_saddlepoint", &check, NULL));
2641064a4176SStefano Zampini       if (check) {
2642064a4176SStefano Zampini         PetscInt i;
2643064a4176SStefano Zampini 
2644064a4176SStefano Zampini         for (i = 0; i < nn; i++) {
2645064a4176SStefano Zampini           KSP       kspC;
2646064a4176SStefano Zampini           PC        pc;
2647064a4176SStefano Zampini           Mat       F, pF;
2648064a4176SStefano Zampini           Vec       x, y;
2649064a4176SStefano Zampini           PetscBool isschur, prec = PETSC_TRUE;
2650064a4176SStefano Zampini 
26519566063dSJacob Faibussowitsch           PetscCall(KSPCreate(PetscObjectComm((PetscObject)ksps[i]), &kspC));
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));
26679566063dSJacob Faibussowitsch             PetscCall(KSPGetPC(kspS2, &pc));
26689566063dSJacob Faibussowitsch             PetscCall(PCSetType(pc, PCKSP));
26699566063dSJacob Faibussowitsch             PetscCall(PCKSPSetKSP(pc, kspS));
26709566063dSJacob Faibussowitsch             PetscCall(KSPSetFromOptions(kspS2));
26719566063dSJacob Faibussowitsch             PetscCall(KSPGetPC(kspS2, &pc));
26729566063dSJacob Faibussowitsch             PetscCall(PCSetUseAmat(pc, 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) {
26799566063dSJacob Faibussowitsch             PetscCall(KSPGetPC(ksps[i], &pc));
26809566063dSJacob Faibussowitsch             PetscCall(KSPSetPC(kspC, pc));
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));
26879566063dSJacob Faibussowitsch           PetscCall(KSPCheckSolve(kspC, pc, 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 
272216b07851SJed Brown .seealso: `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
2734f1580f4eSBarry Smith    PCBDDC - Balancing Domain Decomposition by Constraints preconditioners
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 
2743f1580f4eSBarry Smith    Approximate local solvers are automatically adapted (see [1]) 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 
2754f1580f4eSBarry Smith    Change of basis is performed similarly to [2] 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 
2758f1580f4eSBarry Smith    The PETSc implementation also supports multilevel `PCBDDC` [3]. Coarse grids are partitioned using a `MatPartitioning` object.
275928509bceSStefano Zampini 
2760f1580f4eSBarry Smith    Adaptive selection of primal constraints [4] is supported for SPD systems with high-contrast in the coefficients if MUMPS or MKL_PARDISO are present.
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 
2804be4a8d98Sprj-    References:
2805606c0280SSatish Balay +  * - C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149--168, March 2007
2806606c0280SSatish Balay .  * - A. Klawonn and O. B. Widlund. "Dual-Primal FETI Methods for Linear Elasticity", Communications on Pure and Applied Mathematics Volume 59, Issue 11, pages 1523--1572, November 2006
2807606c0280SSatish Balay .  * - J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", Computing Volume 83, Issue 2--3, pages 55--85, November 2008
2808606c0280SSatish Balay -  * - C. Pechstein and C. R. Dohrmann. "Modern domain decomposition methods BDDC, deluxe scaling, and an algebraic approach", Seminar talk, Linz, December 2013, http://people.ricam.oeaw.ac.at/c.pechstein/pechstein-bddc2013.pdf
2809be4a8d98Sprj- 
2810da1bb401SStefano Zampini    Level: intermediate
2811da1bb401SStefano Zampini 
2812da1bb401SStefano Zampini    Contributed by Stefano Zampini
2813da1bb401SStefano Zampini 
2814d36aa646SPierre Jolivet .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `MATIS`, `PCLU`, `PCGAMG`, `PC`, `PCBDDCSetLocalAdjacencyGraph()`, `PCBDDCSetDofsSplitting()`,
2815f1580f4eSBarry Smith           `PCBDDCSetDirichletBoundaries()`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCSetPrimalVerticesIS()`, `MatNullSpace`, `MatSetNearNullSpace()`,
2816f1580f4eSBarry Smith           `PCBDDCSetChangeOfBasisMat()`, `PCBDDCCreateFETIDPOperators()`, `PCNN`
2817da1bb401SStefano Zampini M*/
2818b2573a8aSBarry Smith 
2819d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
2820d71ae5a4SJacob Faibussowitsch {
2821da1bb401SStefano Zampini   PC_BDDC *pcbddc;
2822da1bb401SStefano Zampini 
2823da1bb401SStefano Zampini   PetscFunctionBegin;
28244dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&pcbddc));
28253ec1f749SStefano Zampini   pc->data = pcbddc;
2826da1bb401SStefano Zampini 
2827da1bb401SStefano Zampini   /* create PCIS data structure */
28289566063dSJacob Faibussowitsch   PetscCall(PCISCreate(pc));
2829da1bb401SStefano Zampini 
28309326c5c6Sstefano_zampini   /* create local graph structure */
28319566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphCreate(&pcbddc->mat_graph));
28329326c5c6Sstefano_zampini 
28339326c5c6Sstefano_zampini   /* BDDC nonzero defaults */
28346d9e27e4SStefano Zampini   pcbddc->use_nnsp                  = PETSC_TRUE;
283508a5cf49SStefano Zampini   pcbddc->use_local_adj             = PETSC_TRUE;
283647d04d0dSStefano Zampini   pcbddc->use_vertices              = PETSC_TRUE;
283747d04d0dSStefano Zampini   pcbddc->use_edges                 = PETSC_TRUE;
28383301b35fSStefano Zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
283914f95afaSStefano Zampini   pcbddc->vertex_size               = 1;
2840c703fcc7SStefano Zampini   pcbddc->recompute_topography      = PETSC_TRUE;
284168457ee5SStefano Zampini   pcbddc->coarse_size               = -1;
284285c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
284347d04d0dSStefano Zampini   pcbddc->coarsening_ratio          = 8;
284457de7509SStefano Zampini   pcbddc->coarse_eqs_per_proc       = 1;
284527b6a85dSStefano Zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
28461e0482f5SStefano Zampini   pcbddc->nedfield                  = -1;
28471e0482f5SStefano Zampini   pcbddc->nedglobal                 = PETSC_TRUE;
2848be12c134Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
2849b96c3477SStefano Zampini   pcbddc->sub_schurs_layers         = -1;
2850bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[0]     = 0.0;
2851bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[1]     = 0.0;
2852b7eb3628SStefano Zampini 
2853da1bb401SStefano Zampini   /* function pointers */
2854da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
285593bd9ae7SStefano Zampini   pc->ops->applytranspose      = PCApplyTranspose_BDDC;
2856da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
2857da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
2858da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
28596b78500eSPatrick Sanan   pc->ops->view                = PCView_BDDC;
28600a545947SLisandro Dalcin   pc->ops->applyrichardson     = NULL;
28610a545947SLisandro Dalcin   pc->ops->applysymmetricleft  = NULL;
28620a545947SLisandro Dalcin   pc->ops->applysymmetricright = NULL;
2863534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
2864534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
28659326c5c6Sstefano_zampini   pc->ops->reset               = PCReset_BDDC;
2866da1bb401SStefano Zampini 
2867da1bb401SStefano Zampini   /* composing function */
28689566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDiscreteGradient_C", PCBDDCSetDiscreteGradient_BDDC));
28699566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDivergenceMat_C", PCBDDCSetDivergenceMat_BDDC));
28709566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetChangeOfBasisMat_C", PCBDDCSetChangeOfBasisMat_BDDC));
28719566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesLocalIS_C", PCBDDCSetPrimalVerticesLocalIS_BDDC));
28729566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesIS_C", PCBDDCSetPrimalVerticesIS_BDDC));
28739566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesLocalIS_C", PCBDDCGetPrimalVerticesLocalIS_BDDC));
28749566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesIS_C", PCBDDCGetPrimalVerticesIS_BDDC));
28759566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetCoarseningRatio_C", PCBDDCSetCoarseningRatio_BDDC));
28769566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevel_C", PCBDDCSetLevel_BDDC));
28779566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetUseExactDirichlet_C", PCBDDCSetUseExactDirichlet_BDDC));
28789566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevels_C", PCBDDCSetLevels_BDDC));
28799566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundaries_C", PCBDDCSetDirichletBoundaries_BDDC));
28809566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundariesLocal_C", PCBDDCSetDirichletBoundariesLocal_BDDC));
28819566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundaries_C", PCBDDCSetNeumannBoundaries_BDDC));
28829566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundariesLocal_C", PCBDDCSetNeumannBoundariesLocal_BDDC));
28839566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundaries_C", PCBDDCGetDirichletBoundaries_BDDC));
28849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundariesLocal_C", PCBDDCGetDirichletBoundariesLocal_BDDC));
28859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundaries_C", PCBDDCGetNeumannBoundaries_BDDC));
28869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundariesLocal_C", PCBDDCGetNeumannBoundariesLocal_BDDC));
28879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplitting_C", PCBDDCSetDofsSplitting_BDDC));
28889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplittingLocal_C", PCBDDCSetDofsSplittingLocal_BDDC));
28899566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", PCBDDCSetLocalAdjacencyGraph_BDDC));
28909566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCCreateFETIDPOperators_C", PCBDDCCreateFETIDPOperators_BDDC));
28919566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetRHS_C", PCBDDCMatFETIDPGetRHS_BDDC));
28929566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetSolution_C", PCBDDCMatFETIDPGetSolution_BDDC));
28939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", PCPreSolveChangeRHS_BDDC));
28949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_BDDC));
28953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2896da1bb401SStefano Zampini }
289743371fb9SStefano Zampini 
289843371fb9SStefano Zampini /*@C
2899f1580f4eSBarry Smith   PCBDDCInitializePackage - This function initializes everything in the `PCBDDC` package. It is called
2900f1580f4eSBarry Smith   from `PCInitializePackage()`.
290143371fb9SStefano Zampini 
290243371fb9SStefano Zampini   Level: developer
290343371fb9SStefano Zampini 
2904f1580f4eSBarry Smith .seealso: `PetscInitialize()`, `PCBDDCFinalizePackage()`
290543371fb9SStefano Zampini @*/
2906d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCInitializePackage(void)
2907d71ae5a4SJacob Faibussowitsch {
290843371fb9SStefano Zampini   int i;
290943371fb9SStefano Zampini 
291043371fb9SStefano Zampini   PetscFunctionBegin;
29113ba16761SJacob Faibussowitsch   if (PCBDDCPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS);
291243371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_TRUE;
29139566063dSJacob Faibussowitsch   PetscCall(PetscRegisterFinalize(PCBDDCFinalizePackage));
291443371fb9SStefano Zampini 
291543371fb9SStefano Zampini   /* general events */
29169566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCTopo", PC_CLASSID, &PC_BDDC_Topology[0]));
29179566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCLKSP", PC_CLASSID, &PC_BDDC_LocalSolvers[0]));
29189566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCLWor", PC_CLASSID, &PC_BDDC_LocalWork[0]));
29199566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCorr", PC_CLASSID, &PC_BDDC_CorrectionSetUp[0]));
29209566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCASet", PC_CLASSID, &PC_BDDC_ApproxSetUp[0]));
29219566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCAApp", PC_CLASSID, &PC_BDDC_ApproxApply[0]));
29229566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCSet", PC_CLASSID, &PC_BDDC_CoarseSetUp[0]));
29239566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCKSP", PC_CLASSID, &PC_BDDC_CoarseSolver[0]));
29249566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCAdap", PC_CLASSID, &PC_BDDC_AdaptiveSetUp[0]));
29259566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCScal", PC_CLASSID, &PC_BDDC_Scaling[0]));
29269566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCSchr", PC_CLASSID, &PC_BDDC_Schurs[0]));
29279566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCDirS", PC_CLASSID, &PC_BDDC_Solves[0][0]));
29289566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCNeuS", PC_CLASSID, &PC_BDDC_Solves[0][1]));
29299566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCoaS", PC_CLASSID, &PC_BDDC_Solves[0][2]));
293043371fb9SStefano Zampini   for (i = 1; i < PETSC_PCBDDC_MAXLEVELS; i++) {
293143371fb9SStefano Zampini     char ename[32];
293243371fb9SStefano Zampini 
29339566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCTopo l%02d", i));
29349566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Topology[i]));
29359566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCLKSP l%02d", i));
29369566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_LocalSolvers[i]));
29379566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCLWor l%02d", i));
29389566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_LocalWork[i]));
29399566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCorr l%02d", i));
29409566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CorrectionSetUp[i]));
29419566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCASet l%02d", i));
29429566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_ApproxSetUp[i]));
29439566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCAApp l%02d", i));
29449566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_ApproxApply[i]));
29459566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCSet l%02d", i));
29469566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CoarseSetUp[i]));
29479566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCKSP l%02d", i));
29489566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CoarseSolver[i]));
29499566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCAdap l%02d", i));
29509566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_AdaptiveSetUp[i]));
29519566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCScal l%02d", i));
29529566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Scaling[i]));
29539566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCSchr l%02d", i));
29549566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Schurs[i]));
29559566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCDirS l%02d", i));
29569566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][0]));
29579566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCNeuS l%02d", i));
29589566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][1]));
29599566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCoaS l%02d", i));
29609566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][2]));
296143371fb9SStefano Zampini   }
29623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
296343371fb9SStefano Zampini }
296443371fb9SStefano Zampini 
296543371fb9SStefano Zampini /*@C
2966f1580f4eSBarry Smith   PCBDDCFinalizePackage - This function frees everything from the `PCBDDC` package. It is
2967f1580f4eSBarry Smith   called from `PetscFinalize()` automatically.
296843371fb9SStefano Zampini 
296943371fb9SStefano Zampini   Level: developer
297043371fb9SStefano Zampini 
2971f1580f4eSBarry Smith .seealso: `PetscFinalize()`, `PCBDDCInitializePackage()`
297243371fb9SStefano Zampini @*/
2973d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCFinalizePackage(void)
2974d71ae5a4SJacob Faibussowitsch {
297543371fb9SStefano Zampini   PetscFunctionBegin;
297643371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_FALSE;
29773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
297843371fb9SStefano Zampini }
2979