xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 4e8208cbcbc709572b8abe32f33c78b69c819375)
1dd01b7e5SBarry Smith #include <petsc/private/pcbddcimpl.h> /*I "petscpc.h" I*/ /* header file for Fortran wrappers */
25e5bbd0aSStefano Zampini #include <petsc/private/pcbddcprivateimpl.h>
33b03a366Sstefano_zampini #include <petscblaslapack.h>
4674ae819SStefano Zampini 
543371fb9SStefano Zampini static PetscBool PCBDDCPackageInitialized = PETSC_FALSE;
643371fb9SStefano Zampini 
7f3d41395Sstefano_zampini static PetscBool  cited      = PETSC_FALSE;
89371c9d4SSatish Balay static const char citation[] = "@article{ZampiniPCBDDC,\n"
9f3d41395Sstefano_zampini                                "author = {Stefano Zampini},\n"
10f3d41395Sstefano_zampini                                "title = {{PCBDDC}: A Class of Robust Dual-Primal Methods in {PETS}c},\n"
11f3d41395Sstefano_zampini                                "journal = {SIAM Journal on Scientific Computing},\n"
12f3d41395Sstefano_zampini                                "volume = {38},\n"
13f3d41395Sstefano_zampini                                "number = {5},\n"
14f3d41395Sstefano_zampini                                "pages = {S282-S306},\n"
15f3d41395Sstefano_zampini                                "year = {2016},\n"
16f3d41395Sstefano_zampini                                "doi = {10.1137/15M1025785},\n"
17f3d41395Sstefano_zampini                                "URL = {http://dx.doi.org/10.1137/15M1025785},\n"
18f3d41395Sstefano_zampini                                "eprint = {http://dx.doi.org/10.1137/15M1025785}\n"
19f3d41395Sstefano_zampini                                "}\n";
20f3d41395Sstefano_zampini 
2143371fb9SStefano Zampini PetscLogEvent PC_BDDC_Topology[PETSC_PCBDDC_MAXLEVELS];
2243371fb9SStefano Zampini PetscLogEvent PC_BDDC_LocalSolvers[PETSC_PCBDDC_MAXLEVELS];
2343371fb9SStefano Zampini PetscLogEvent PC_BDDC_LocalWork[PETSC_PCBDDC_MAXLEVELS];
2443371fb9SStefano Zampini PetscLogEvent PC_BDDC_CorrectionSetUp[PETSC_PCBDDC_MAXLEVELS];
258ead10e4SStefano Zampini PetscLogEvent PC_BDDC_ApproxSetUp[PETSC_PCBDDC_MAXLEVELS];
268ead10e4SStefano Zampini PetscLogEvent PC_BDDC_ApproxApply[PETSC_PCBDDC_MAXLEVELS];
2743371fb9SStefano Zampini PetscLogEvent PC_BDDC_CoarseSetUp[PETSC_PCBDDC_MAXLEVELS];
2843371fb9SStefano Zampini PetscLogEvent PC_BDDC_CoarseSolver[PETSC_PCBDDC_MAXLEVELS];
2943371fb9SStefano Zampini PetscLogEvent PC_BDDC_AdaptiveSetUp[PETSC_PCBDDC_MAXLEVELS];
3043371fb9SStefano Zampini PetscLogEvent PC_BDDC_Scaling[PETSC_PCBDDC_MAXLEVELS];
3143371fb9SStefano Zampini PetscLogEvent PC_BDDC_Schurs[PETSC_PCBDDC_MAXLEVELS];
3255c176c0SStefano Zampini PetscLogEvent PC_BDDC_Solves[PETSC_PCBDDC_MAXLEVELS][3];
3343371fb9SStefano Zampini 
34bc960bbfSJed Brown const char *const PCBDDCInterfaceExtTypes[] = {"DIRICHLET", "LUMP", "PCBDDCInterfaceExtType", "PC_BDDC_INTERFACE_EXT_", NULL};
35bc960bbfSJed Brown 
3666976f2fSJacob Faibussowitsch static PetscErrorCode PCApply_BDDC(PC, Vec, Vec);
370369aaf7SStefano Zampini 
PCSetFromOptions_BDDC(PC pc,PetscOptionItems PetscOptionsObject)38ce78bad3SBarry Smith static PetscErrorCode PCSetFromOptions_BDDC(PC pc, PetscOptionItems PetscOptionsObject)
39d71ae5a4SJacob Faibussowitsch {
400c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC *)pc->data;
41e569e4e1SStefano Zampini   PetscInt  nt, i;
429de2952eSStefano Zampini   char      load[PETSC_MAX_PATH_LEN] = {'\0'};
439de2952eSStefano Zampini   PetscBool flg;
440c7d97c5SJed Brown 
450c7d97c5SJed Brown   PetscFunctionBegin;
46d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "BDDC options");
479de2952eSStefano Zampini   /* Load customization from binary file (debugging) */
489de2952eSStefano Zampini   PetscCall(PetscOptionsString("-pc_bddc_load", "Load customization from file (intended for debug)", "none", load, load, sizeof(load), &flg));
499de2952eSStefano Zampini   if (flg) {
509de2952eSStefano Zampini     size_t len;
519de2952eSStefano Zampini 
529de2952eSStefano Zampini     PetscCall(PetscStrlen(load, &len));
539de2952eSStefano Zampini     PetscCall(PCBDDCLoadOrViewCustomization(pc, PETSC_TRUE, len ? load : NULL));
549de2952eSStefano Zampini   }
558eeda7d8SStefano Zampini   /* Verbose debugging */
569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_check_level", "Verbose output for PCBDDC (intended for debug)", "none", pcbddc->dbg_flag, &pcbddc->dbg_flag, NULL));
57a13144ffSStefano Zampini   /* Approximate solvers */
589566063dSJacob 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));
59bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET) {
609566063dSJacob 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));
619566063dSJacob 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));
62bc960bbfSJed Brown   } else {
63bc960bbfSJed Brown     /* This flag is needed/implied by lumping */
64bc960bbfSJed Brown     pcbddc->switch_static = PETSC_TRUE;
65bc960bbfSJed Brown   }
669566063dSJacob 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));
679566063dSJacob 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));
686b78500eSPatrick Sanan   /* Primal space customization */
699566063dSJacob 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));
709de2952eSStefano Zampini   PetscCall(PetscOptionsInt("-pc_bddc_local_mat_graph_square", "Square adjacency graph of local mat for interface analysis", "none", pcbddc->local_adj_square, &pcbddc->local_adj_square, NULL));
719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_graph_maxcount", "Maximum number of shared subdomains for a connected component", "none", pcbddc->graphmaxcount, &pcbddc->graphmaxcount, NULL));
729566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_corner_selection", "Activates face-based corner selection", "none", pcbddc->corner_selection, &pcbddc->corner_selection, NULL));
739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_vertices", "Use or not corner dofs in coarse space", "none", pcbddc->use_vertices, &pcbddc->use_vertices, NULL));
749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_edges", "Use or not edge constraints in coarse space", "none", pcbddc->use_edges, &pcbddc->use_edges, NULL));
759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_faces", "Use or not face constraints in coarse space", "none", pcbddc->use_faces, &pcbddc->use_faces, NULL));
769566063dSJacob 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));
779566063dSJacob 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));
789566063dSJacob 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));
799566063dSJacob 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));
808eeda7d8SStefano Zampini   /* Change of basis */
819566063dSJacob 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));
829566063dSJacob 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));
83ad540459SPierre Jolivet   if (!pcbddc->use_change_of_basis) pcbddc->use_change_on_faces = PETSC_FALSE;
848eeda7d8SStefano Zampini   /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */
859566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_switch_static", "Switch on static condensation ops around the interface preconditioner", "none", pcbddc->switch_static, &pcbddc->switch_static, NULL));
869566063dSJacob 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));
87e569e4e1SStefano Zampini   i = pcbddc->coarsening_ratio;
889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_coarsening_ratio", "Set coarsening ratio used in multilevel coarsening", "PCBDDCSetCoarseningRatio", i, &i, NULL));
899566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetCoarseningRatio(pc, i));
90e569e4e1SStefano Zampini   i = pcbddc->max_levels;
919566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_levels", "Set maximum number of levels for multilevel", "PCBDDCSetLevels", i, &i, NULL));
929566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetLevels(pc, i));
939566063dSJacob 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));
949566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_coarse_estimates", "Use estimated eigenvalues for coarse problem", "none", pcbddc->use_coarse_estimates, &pcbddc->use_coarse_estimates, NULL));
959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_deluxe_scaling", "Use deluxe scaling for BDDC", "none", pcbddc->use_deluxe_scaling, &pcbddc->use_deluxe_scaling, NULL));
969566063dSJacob 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));
979566063dSJacob 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));
989566063dSJacob 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));
999566063dSJacob 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));
1009566063dSJacob 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));
1019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_deluxe_singlemat", "Collapse deluxe operators", "none", pcbddc->deluxe_singlemat, &pcbddc->deluxe_singlemat, NULL));
1029566063dSJacob 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));
103bd2a564bSStefano Zampini   nt = 2;
1049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRealArray("-pc_bddc_adaptive_threshold", "Thresholds to be used for adaptive selection of constraints", "none", pcbddc->adaptive_threshold, &nt, NULL));
105bd2a564bSStefano Zampini   if (nt == 1) pcbddc->adaptive_threshold[1] = pcbddc->adaptive_threshold[0];
1069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_adaptive_nmin", "Minimum number of constraints per connected components", "none", pcbddc->adaptive_nmin, &pcbddc->adaptive_nmin, NULL));
1079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_adaptive_nmax", "Maximum number of constraints per connected components", "none", pcbddc->adaptive_nmax, &pcbddc->adaptive_nmax, NULL));
1089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_symmetric", "Symmetric computation of primal basis functions", "none", pcbddc->symmetric_primal, &pcbddc->symmetric_primal, NULL));
1099566063dSJacob 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));
1109566063dSJacob 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));
1119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_benign_change", "Compute the pressure change of basis explicitly", "none", pcbddc->benign_change_explicit, &pcbddc->benign_change_explicit, NULL));
1129566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_benign_compute_correction", "Compute the benign correction during PreSolve", "none", pcbddc->benign_compute_correction, &pcbddc->benign_compute_correction, NULL));
1139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_nonetflux", "Automatic computation of no-net-flux quadrature weights", "none", pcbddc->compute_nonetflux, &pcbddc->compute_nonetflux, NULL));
1149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_detect_disconnected", "Detects disconnected subdomains", "none", pcbddc->detect_disconnected, &pcbddc->detect_disconnected, NULL));
1159566063dSJacob 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));
1169566063dSJacob 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));
117d0609cedSBarry Smith   PetscOptionsHeadEnd();
1183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1190c7d97c5SJed Brown }
1206b78500eSPatrick Sanan 
PCView_BDDC(PC pc,PetscViewer viewer)121d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_BDDC(PC pc, PetscViewer viewer)
122d71ae5a4SJacob Faibussowitsch {
1236b78500eSPatrick Sanan   PC_BDDC     *pcbddc = (PC_BDDC *)pc->data;
124e9627c49SStefano Zampini   PC_IS       *pcis   = (PC_IS *)pc->data;
12571783a16SStefano Zampini   PetscBool    isascii;
126e9627c49SStefano Zampini   PetscSubcomm subcomm;
127e9627c49SStefano Zampini   PetscViewer  subviewer;
1286b78500eSPatrick Sanan 
1296b78500eSPatrick Sanan   PetscFunctionBegin;
1309566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1316b78500eSPatrick Sanan   /* ASCII viewer */
1326b78500eSPatrick Sanan   if (isascii) {
1334b2aedd3SStefano Zampini     PetscMPIInt color, rank, size;
134fbad9177SStefano Zampini     PetscInt64  loc[7], gsum[6], gmax[6], gmin[6], totbenign;
135e9627c49SStefano Zampini     PetscScalar interface_size;
136e9627c49SStefano Zampini     PetscReal   ratio1 = 0., ratio2 = 0.;
137e9627c49SStefano Zampini     Vec         counter;
1386b78500eSPatrick Sanan 
13948a46eb9SPierre Jolivet     if (!pc->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, "  Partial information available: preconditioner has not been setup yet\n"));
14063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use verbose output: %" PetscInt_FMT "\n", pcbddc->dbg_flag));
1419566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use user-defined CSR: %d\n", !!pcbddc->mat_graph->nvtxs_csr));
1429566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use local mat graph: %d\n", pcbddc->use_local_adj && !pcbddc->mat_graph->nvtxs_csr));
143e9627c49SStefano Zampini     if (pcbddc->mat_graph->twodim) {
1449566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Connectivity graph topological dimension: 2\n"));
145e9627c49SStefano Zampini     } else {
1469566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Connectivity graph topological dimension: 3\n"));
147e9627c49SStefano Zampini     }
1481690c2aeSBarry Smith     if (pcbddc->graphmaxcount != PETSC_INT_MAX) PetscCall(PetscViewerASCIIPrintf(viewer, "  Graph max count: %" PetscInt_FMT "\n", pcbddc->graphmaxcount));
1499566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Corner selection: %d (selected %d)\n", pcbddc->corner_selection, pcbddc->corner_selected));
15063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use vertices: %d (vertex size %" PetscInt_FMT ")\n", pcbddc->use_vertices, pcbddc->vertex_size));
1519566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use edges: %d\n", pcbddc->use_edges));
1529566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use faces: %d\n", pcbddc->use_faces));
1539566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use true near null space: %d\n", pcbddc->use_nnsp_true));
1549566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use QR for single constraints on cc: %d\n", pcbddc->use_qr_single));
1559566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use change of basis on local edge nodes: %d\n", pcbddc->use_change_of_basis));
1569566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use change of basis on local face nodes: %d\n", pcbddc->use_change_on_faces));
1579566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  User defined change of basis matrix: %d\n", !!pcbddc->user_ChangeOfBasisMatrix));
1589566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Has change of basis matrix: %d\n", !!pcbddc->ChangeOfBasisMatrix));
1599566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Eliminate dirichlet boundary dofs: %d\n", pcbddc->eliminate_dirdofs));
1609566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Switch on static condensation ops around the interface preconditioner: %d\n", pcbddc->switch_static));
1619566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use exact dirichlet trick: %d\n", pcbddc->use_exact_dirichlet_trick));
1629566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Interface extension: %s\n", PCBDDCInterfaceExtTypes[pcbddc->interface_extension]));
16363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Multilevel max levels: %" PetscInt_FMT "\n", pcbddc->max_levels));
16463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Multilevel coarsening ratio: %" PetscInt_FMT "\n", pcbddc->coarsening_ratio));
1659566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use estimated eigs for coarse problem: %d\n", pcbddc->use_coarse_estimates));
1669566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use deluxe scaling: %d\n", pcbddc->use_deluxe_scaling));
1679566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use deluxe zerorows: %d\n", pcbddc->deluxe_zerorows));
1689566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use deluxe singlemat: %d\n", pcbddc->deluxe_singlemat));
1699566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Rebuild interface graph for Schur principal minors: %d\n", pcbddc->sub_schurs_rebuild));
17063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of dofs' layers for the computation of principal minors: %" PetscInt_FMT "\n", pcbddc->sub_schurs_layers));
1719566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use user CSR graph to compute successive layers: %d\n", pcbddc->sub_schurs_use_useradj));
172bd2a564bSStefano Zampini     if (pcbddc->adaptive_threshold[1] != pcbddc->adaptive_threshold[0]) {
17363a3b9bcSJacob 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]));
174bd2a564bSStefano Zampini     } else {
17563a3b9bcSJacob 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]));
176bd2a564bSStefano Zampini     }
17763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Min constraints / connected component: %" PetscInt_FMT "\n", pcbddc->adaptive_nmin));
17863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Max constraints / connected component: %" PetscInt_FMT "\n", pcbddc->adaptive_nmax));
1799566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Invert exact Schur complement for adaptive selection: %d\n", pcbddc->sub_schurs_exact_schur));
1809566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Symmetric computation of primal basis functions: %d\n", pcbddc->symmetric_primal));
18163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Num. Procs. to map coarse adjacency list: %" PetscInt_FMT "\n", pcbddc->coarse_adj_red));
18263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Coarse eqs per proc (significant at the coarsest level): %" PetscInt_FMT "\n", pcbddc->coarse_eqs_per_proc));
1839566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Detect disconnected: %d (filter %d)\n", pcbddc->detect_disconnected, pcbddc->detect_disconnected_filter));
1849566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Benign subspace trick: %d (change explicit %d)\n", pcbddc->benign_saddle_point, pcbddc->benign_change_explicit));
1859566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Benign subspace trick is active: %d\n", pcbddc->benign_have_null));
1869566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Algebraic computation of no-net-flux: %d\n", pcbddc->compute_nonetflux));
1873ba16761SJacob Faibussowitsch     if (!pc->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
1886b78500eSPatrick Sanan 
189fbad9177SStefano Zampini     /* compute interface size */
1909566063dSJacob Faibussowitsch     PetscCall(VecSet(pcis->vec1_B, 1.0));
1919566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(pc->pmat, &counter, NULL));
1929566063dSJacob Faibussowitsch     PetscCall(VecSet(counter, 0.0));
1939566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, counter, INSERT_VALUES, SCATTER_REVERSE));
1949566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, counter, INSERT_VALUES, SCATTER_REVERSE));
1959566063dSJacob Faibussowitsch     PetscCall(VecSum(counter, &interface_size));
1969566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&counter));
197fbad9177SStefano Zampini 
198fbad9177SStefano Zampini     /* compute some statistics on the domain decomposition */
199e9627c49SStefano Zampini     gsum[0] = 1;
200fbad9177SStefano Zampini     gsum[1] = gsum[2] = gsum[3] = gsum[4] = gsum[5] = 0;
201e9627c49SStefano Zampini     loc[0]                                          = !!pcis->n;
202e9627c49SStefano Zampini     loc[1]                                          = pcis->n - pcis->n_B;
203e9627c49SStefano Zampini     loc[2]                                          = pcis->n_B;
204e9627c49SStefano Zampini     loc[3]                                          = pcbddc->local_primal_size;
205345ecf6cSStefano Zampini     loc[4]                                          = pcis->n;
206fbad9177SStefano Zampini     loc[5]                                          = pcbddc->n_local_subs > 0 ? pcbddc->n_local_subs : (pcis->n ? 1 : 0);
207fbad9177SStefano Zampini     loc[6]                                          = pcbddc->benign_n;
2089566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(loc, gsum, 6, MPIU_INT64, MPI_SUM, 0, PetscObjectComm((PetscObject)pc)));
209fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = -1;
2109566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(loc, gmax, 6, MPIU_INT64, MPI_MAX, 0, PetscObjectComm((PetscObject)pc)));
2111690c2aeSBarry Smith     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = PETSC_INT_MAX;
2129566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(loc, gmin, 6, MPIU_INT64, MPI_MIN, 0, PetscObjectComm((PetscObject)pc)));
2139566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&loc[6], &totbenign, 1, MPIU_INT64, MPI_SUM, 0, PetscObjectComm((PetscObject)pc)));
214e9627c49SStefano Zampini     if (pcbddc->coarse_size) {
215e9627c49SStefano Zampini       ratio1 = pc->pmat->rmap->N / (1. * pcbddc->coarse_size);
216e9627c49SStefano Zampini       ratio2 = PetscRealPart(interface_size) / pcbddc->coarse_size;
217e9627c49SStefano Zampini     }
21863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "********************************** STATISTICS AT LEVEL %" PetscInt_FMT " **********************************\n", pcbddc->current_level));
21963a3b9bcSJacob 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));
22063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Coarsening ratios: all/coarse %" PetscInt_FMT " interface/coarse %" PetscInt_FMT "\n", (PetscInt)ratio1, (PetscInt)ratio2));
221835f2295SStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Active processes : %" PetscInt64_FMT "\n", gsum[0]));
222835f2295SStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Total subdomains : %" PetscInt64_FMT "\n", gsum[5]));
223835f2295SStefano Zampini     if (pcbddc->benign_have_null) PetscCall(PetscViewerASCIIPrintf(viewer, "  Benign subs      : %" PetscInt64_FMT "\n", totbenign));
2249566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Dofs type        :\tMIN\tMAX\tMEAN\n"));
225835f2295SStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Interior  dofs   :\t%" PetscInt64_FMT "\t%" PetscInt64_FMT "\t%" PetscInt64_FMT "\n", gmin[1], gmax[1], gsum[1] / gsum[0]));
226835f2295SStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Interface dofs   :\t%" PetscInt64_FMT "\t%" PetscInt64_FMT "\t%" PetscInt64_FMT "\n", gmin[2], gmax[2], gsum[2] / gsum[0]));
227835f2295SStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Primal    dofs   :\t%" PetscInt64_FMT "\t%" PetscInt64_FMT "\t%" PetscInt64_FMT "\n", gmin[3], gmax[3], gsum[3] / gsum[0]));
228835f2295SStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Local     dofs   :\t%" PetscInt64_FMT "\t%" PetscInt64_FMT "\t%" PetscInt64_FMT "\n", gmin[4], gmax[4], gsum[4] / gsum[0]));
229835f2295SStefano Zampini     PetscCall(PetscViewerASCIIPrintf(viewer, "  Local     subs   :\t%" PetscInt64_FMT "\t%" PetscInt64_FMT "\n", gmin[5], gmax[5]));
2309566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
23115579a77SStefano Zampini 
2329566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc), &rank));
23315579a77SStefano Zampini 
23415579a77SStefano Zampini     /* local solvers */
2359566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetSubViewer(viewer, PetscObjectComm((PetscObject)pcbddc->ksp_D), &subviewer));
236dd400576SPatrick Sanan     if (rank == 0) {
2379566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(subviewer, "--- Interior solver (rank 0)\n"));
2389566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(subviewer));
2399566063dSJacob Faibussowitsch       PetscCall(KSPView(pcbddc->ksp_D, subviewer));
2409566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(subviewer));
2419566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(subviewer, "--- Correction solver (rank 0)\n"));
2429566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(subviewer));
2439566063dSJacob Faibussowitsch       PetscCall(KSPView(pcbddc->ksp_R, subviewer));
2449566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(subviewer));
2459566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(subviewer));
24615579a77SStefano Zampini     }
2479566063dSJacob Faibussowitsch     PetscCall(PetscViewerRestoreSubViewer(viewer, PetscObjectComm((PetscObject)pcbddc->ksp_D), &subviewer));
248fbad9177SStefano Zampini     /* the coarse problem can be handled by a different communicator */
249e9627c49SStefano Zampini     if (pcbddc->coarse_ksp) color = 1;
250e9627c49SStefano Zampini     else color = 0;
2519566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
2529566063dSJacob Faibussowitsch     PetscCall(PetscSubcommCreate(PetscObjectComm((PetscObject)pc), &subcomm));
2539566063dSJacob Faibussowitsch     PetscCall(PetscSubcommSetNumber(subcomm, PetscMin(size, 2)));
2549566063dSJacob Faibussowitsch     PetscCall(PetscSubcommSetTypeGeneral(subcomm, color, rank));
2559566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetSubViewer(viewer, PetscSubcommChild(subcomm), &subviewer));
256e9627c49SStefano Zampini     if (color == 1) {
2579566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(subviewer, "--- Coarse solver\n"));
2589566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(subviewer));
2599566063dSJacob Faibussowitsch       PetscCall(KSPView(pcbddc->coarse_ksp, subviewer));
2609566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(subviewer));
2619566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(subviewer));
262e9627c49SStefano Zampini     }
2639566063dSJacob Faibussowitsch     PetscCall(PetscViewerRestoreSubViewer(viewer, PetscSubcommChild(subcomm), &subviewer));
2649566063dSJacob Faibussowitsch     PetscCall(PetscSubcommDestroy(&subcomm));
2659566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
266e9627c49SStefano Zampini   }
2673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2686b78500eSPatrick Sanan }
269a13144ffSStefano Zampini 
PCBDDCSetDiscreteGradient_BDDC(PC pc,Mat G,PetscInt order,PetscInt field,PetscBool global,PetscBool conforming)270d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDiscreteGradient_BDDC(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
271d71ae5a4SJacob Faibussowitsch {
272a13144ffSStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
273a13144ffSStefano Zampini 
274a13144ffSStefano Zampini   PetscFunctionBegin;
2759566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)G));
2769566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->discretegradient));
277a13144ffSStefano Zampini   pcbddc->discretegradient = G;
278a13144ffSStefano Zampini   pcbddc->nedorder         = order > 0 ? order : -order;
279495a2a07SStefano Zampini   pcbddc->nedfield         = field;
2801e0482f5SStefano Zampini   pcbddc->nedglobal        = global;
2811e0482f5SStefano Zampini   pcbddc->conforming       = conforming;
2823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
283a13144ffSStefano Zampini }
284a13144ffSStefano Zampini 
285a13144ffSStefano Zampini /*@
28698ad52f2SBarry Smith   PCBDDCSetDiscreteGradient - Sets the discrete gradient to be used by the `PCBDDC` preconditioner
287a13144ffSStefano Zampini 
288c3339decSBarry Smith   Collective
289a13144ffSStefano Zampini 
290a13144ffSStefano Zampini   Input Parameters:
291a13144ffSStefano Zampini + pc         - the preconditioning context
292f1580f4eSBarry Smith . G          - the discrete gradient matrix (in `MATAIJ` format)
293a13144ffSStefano Zampini . order      - the order of the Nedelec space (1 for the lowest order)
294495a2a07SStefano Zampini . field      - the field id of the Nedelec dofs (not used if the fields have not been specified)
29598ad52f2SBarry Smith . global     - the type of global ordering for the rows of `G`
296a13144ffSStefano Zampini - conforming - whether the mesh is conforming or not
297a13144ffSStefano Zampini 
298a13144ffSStefano Zampini   Level: advanced
299a13144ffSStefano Zampini 
300f1580f4eSBarry Smith   Note:
30120f4b53cSBarry Smith   The discrete gradient matrix `G` is used to analyze the subdomain edges, and it should not contain any zero entry.
302495a2a07SStefano Zampini   For variable order spaces, the order should be set to zero.
30398ad52f2SBarry Smith   If `global` is `PETSC_TRUE`, the rows of `G` should be given in global ordering for the whole dofs;
30498ad52f2SBarry Smith   if `PETSC_FALSE`, the ordering should be global for the Nedelec field.
3051e0482f5SStefano 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
3061e0482f5SStefano Zampini   and geid the one for the Nedelec field.
307a13144ffSStefano Zampini 
308562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDofsSplitting()`, `PCBDDCSetDofsSplittingLocal()`, `MATAIJ`, `PCBDDCSetDivergenceMat()`
309a13144ffSStefano Zampini @*/
PCBDDCSetDiscreteGradient(PC pc,Mat G,PetscInt order,PetscInt field,PetscBool global,PetscBool conforming)310d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDiscreteGradient(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
311d71ae5a4SJacob Faibussowitsch {
312a13144ffSStefano Zampini   PetscFunctionBegin;
313a13144ffSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
314a13144ffSStefano Zampini   PetscValidHeaderSpecific(G, MAT_CLASSID, 2);
315a13144ffSStefano Zampini   PetscValidLogicalCollectiveInt(pc, order, 3);
3161e0482f5SStefano Zampini   PetscValidLogicalCollectiveInt(pc, field, 4);
3171e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc, global, 5);
3181e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc, conforming, 6);
3191e0482f5SStefano Zampini   PetscCheckSameComm(pc, 1, G, 2);
320cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDiscreteGradient_C", (PC, Mat, PetscInt, PetscInt, PetscBool, PetscBool), (pc, G, order, field, global, conforming));
3213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
322a13144ffSStefano Zampini }
323a13144ffSStefano Zampini 
PCBDDCSetDivergenceMat_BDDC(PC pc,Mat divudotp,PetscBool trans,IS vl2l)324d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDivergenceMat_BDDC(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
325d71ae5a4SJacob Faibussowitsch {
326a198735bSStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
3276b78500eSPatrick Sanan 
328a198735bSStefano Zampini   PetscFunctionBegin;
3299566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)divudotp));
3309566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->divudotp));
331a198735bSStefano Zampini   pcbddc->divudotp          = divudotp;
3328ae0ca82SStefano Zampini   pcbddc->divudotp_trans    = trans;
333a198735bSStefano Zampini   pcbddc->compute_nonetflux = PETSC_TRUE;
334a198735bSStefano Zampini   if (vl2l) {
3359566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)vl2l));
3369566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&pcbddc->divudotp_vl2l));
337a198735bSStefano Zampini     pcbddc->divudotp_vl2l = vl2l;
338a198735bSStefano Zampini   }
3393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
340a198735bSStefano Zampini }
3413d996552SStefano Zampini 
342a198735bSStefano Zampini /*@
34398ad52f2SBarry Smith   PCBDDCSetDivergenceMat - Sets the linear operator representing \int_\Omega \div {\bf u} \cdot p dx for the `PCBDDC` preconditioner
344a198735bSStefano Zampini 
345c3339decSBarry Smith   Collective
346a198735bSStefano Zampini 
347a198735bSStefano Zampini   Input Parameters:
348a198735bSStefano Zampini + pc       - the preconditioning context
349f1580f4eSBarry Smith . divudotp - the matrix (must be of type `MATIS`)
35098ad52f2SBarry Smith . trans    - if `PETSC_FALSE` (resp. `PETSC_TRUE`), then pressures are in the test (trial) space and velocities are in the trial (test) space.
35198ad52f2SBarry Smith - vl2l     - optional index set describing the local (wrt the local matrix in `divudotp`) to local (wrt the local matrix
3527addb90fSBarry Smith              in the matrix used to construct the preconditioner) map for the velocities
353a198735bSStefano Zampini 
354a198735bSStefano Zampini   Level: advanced
355a198735bSStefano Zampini 
35695452b02SPatrick Sanan   Notes:
35795452b02SPatrick Sanan   This auxiliary matrix is used to compute quadrature weights representing the net-flux across subdomain boundaries
358f1580f4eSBarry Smith 
3597addb90fSBarry Smith   If `vl2l` is `NULL`, the local ordering for velocities in `divudotp` should match that of the matrix used to construct the preconditioner
360a198735bSStefano Zampini 
361562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDiscreteGradient()`
362a198735bSStefano Zampini @*/
PCBDDCSetDivergenceMat(PC pc,Mat divudotp,PetscBool trans,IS vl2l)363d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDivergenceMat(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
364d71ae5a4SJacob Faibussowitsch {
365a198735bSStefano Zampini   PetscBool ismatis;
366a198735bSStefano Zampini 
367a198735bSStefano Zampini   PetscFunctionBegin;
368a198735bSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
369a198735bSStefano Zampini   PetscValidHeaderSpecific(divudotp, MAT_CLASSID, 2);
370a198735bSStefano Zampini   PetscCheckSameComm(pc, 1, divudotp, 2);
3718ae0ca82SStefano Zampini   PetscValidLogicalCollectiveBool(pc, trans, 3);
3721b24a7afSStefano Zampini   if (vl2l) PetscValidHeaderSpecific(vl2l, IS_CLASSID, 4);
3739566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)divudotp, MATIS, &ismatis));
37428b400f6SJacob Faibussowitsch   PetscCheck(ismatis, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Divergence matrix needs to be of type MATIS");
375cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDivergenceMat_C", (PC, Mat, PetscBool, IS), (pc, divudotp, trans, vl2l));
3763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
377a198735bSStefano Zampini }
3782d505d7fSStefano Zampini 
PCBDDCSetChangeOfBasisMat_BDDC(PC pc,Mat change,PetscBool interior)379d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change, PetscBool interior)
380d71ae5a4SJacob Faibussowitsch {
381b9b85e73SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
382b9b85e73SStefano Zampini 
383b9b85e73SStefano Zampini   PetscFunctionBegin;
3849566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)change));
3859566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->user_ChangeOfBasisMatrix));
386b9b85e73SStefano Zampini   pcbddc->user_ChangeOfBasisMatrix = change;
3871dd7afcfSStefano Zampini   pcbddc->change_interior          = interior;
3883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
389b9b85e73SStefano Zampini }
39032fe681dSStefano Zampini 
391b9b85e73SStefano Zampini /*@
392906d46d4SStefano Zampini   PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs
393b9b85e73SStefano Zampini 
394c3339decSBarry Smith   Collective
395b9b85e73SStefano Zampini 
396b9b85e73SStefano Zampini   Input Parameters:
397b9b85e73SStefano Zampini + pc       - the preconditioning context
3981dd7afcfSStefano Zampini . change   - the change of basis matrix
3991dd7afcfSStefano Zampini - interior - whether or not the change of basis modifies interior dofs
400b9b85e73SStefano Zampini 
401b9b85e73SStefano Zampini   Level: intermediate
402b9b85e73SStefano Zampini 
403562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`
404b9b85e73SStefano Zampini @*/
PCBDDCSetChangeOfBasisMat(PC pc,Mat change,PetscBool interior)405d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change, PetscBool interior)
406d71ae5a4SJacob Faibussowitsch {
407b9b85e73SStefano Zampini   PetscFunctionBegin;
408b9b85e73SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
409b9b85e73SStefano Zampini   PetscValidHeaderSpecific(change, MAT_CLASSID, 2);
410906d46d4SStefano Zampini   PetscCheckSameComm(pc, 1, change, 2);
411906d46d4SStefano Zampini   if (pc->mat) {
412906d46d4SStefano Zampini     PetscInt rows_c, cols_c, rows, cols;
4139566063dSJacob Faibussowitsch     PetscCall(MatGetSize(pc->mat, &rows, &cols));
4149566063dSJacob Faibussowitsch     PetscCall(MatGetSize(change, &rows_c, &cols_c));
41563a3b9bcSJacob 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);
41663a3b9bcSJacob 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);
4179566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(pc->mat, &rows, &cols));
4189566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(change, &rows_c, &cols_c));
41963a3b9bcSJacob 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);
42063a3b9bcSJacob 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);
421906d46d4SStefano Zampini   }
422cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetChangeOfBasisMat_C", (PC, Mat, PetscBool), (pc, change, interior));
4233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
424b9b85e73SStefano Zampini }
4252d505d7fSStefano Zampini 
PCBDDCSetPrimalVerticesIS_BDDC(PC pc,IS PrimalVertices)426d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetPrimalVerticesIS_BDDC(PC pc, IS PrimalVertices)
427d71ae5a4SJacob Faibussowitsch {
42830368db7SStefano Zampini   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
42956282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
43030368db7SStefano Zampini 
43130368db7SStefano Zampini   PetscFunctionBegin;
4329566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)PrimalVertices));
43348a46eb9SPierre Jolivet   if (pcbddc->user_primal_vertices) PetscCall(ISEqual(PrimalVertices, pcbddc->user_primal_vertices, &isequal));
4349566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices));
4359566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local));
43630368db7SStefano Zampini   pcbddc->user_primal_vertices = PrimalVertices;
43756282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
4383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
43930368db7SStefano Zampini }
440ab8c8b98SStefano Zampini 
44130368db7SStefano Zampini /*@
442f1580f4eSBarry Smith   PCBDDCSetPrimalVerticesIS - Set additional user defined primal vertices in `PCBDDC`
44330368db7SStefano Zampini 
44430368db7SStefano Zampini   Collective
44530368db7SStefano Zampini 
44630368db7SStefano Zampini   Input Parameters:
44730368db7SStefano Zampini + pc             - the preconditioning context
44830368db7SStefano Zampini - PrimalVertices - index set of primal vertices in global numbering (can be empty)
44930368db7SStefano Zampini 
45030368db7SStefano Zampini   Level: intermediate
45130368db7SStefano Zampini 
452f1580f4eSBarry Smith   Note:
45330368db7SStefano Zampini   Any process can list any global node
45430368db7SStefano Zampini 
455562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`, `PCBDDCGetPrimalVerticesLocalIS()`
45630368db7SStefano Zampini @*/
PCBDDCSetPrimalVerticesIS(PC pc,IS PrimalVertices)457d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetPrimalVerticesIS(PC pc, IS PrimalVertices)
458d71ae5a4SJacob Faibussowitsch {
45930368db7SStefano Zampini   PetscFunctionBegin;
46030368db7SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
46130368db7SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices, IS_CLASSID, 2);
46230368db7SStefano Zampini   PetscCheckSameComm(pc, 1, PrimalVertices, 2);
463cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetPrimalVerticesIS_C", (PC, IS), (pc, PrimalVertices));
4643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46530368db7SStefano Zampini }
4662d505d7fSStefano Zampini 
PCBDDCGetPrimalVerticesIS_BDDC(PC pc,IS * is)467d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetPrimalVerticesIS_BDDC(PC pc, IS *is)
468d71ae5a4SJacob Faibussowitsch {
4693100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
4703100ebe3SStefano Zampini 
4713100ebe3SStefano Zampini   PetscFunctionBegin;
4723100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices;
4733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4743100ebe3SStefano Zampini }
4753100ebe3SStefano Zampini 
4763100ebe3SStefano Zampini /*@
477f1580f4eSBarry Smith   PCBDDCGetPrimalVerticesIS - Get user defined primal vertices set with `PCBDDCSetPrimalVerticesIS()`
4783100ebe3SStefano Zampini 
4793100ebe3SStefano Zampini   Collective
4803100ebe3SStefano Zampini 
481f1580f4eSBarry Smith   Input Parameter:
4823100ebe3SStefano Zampini . pc - the preconditioning context
4833100ebe3SStefano Zampini 
484f1580f4eSBarry Smith   Output Parameter:
48520f4b53cSBarry Smith . is - index set of primal vertices in global numbering (`NULL` if not set)
4863100ebe3SStefano Zampini 
4873100ebe3SStefano Zampini   Level: intermediate
4883100ebe3SStefano Zampini 
489562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`, `PCBDDCGetPrimalVerticesLocalIS()`
4903100ebe3SStefano Zampini @*/
PCBDDCGetPrimalVerticesIS(PC pc,IS * is)491d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetPrimalVerticesIS(PC pc, IS *is)
492d71ae5a4SJacob Faibussowitsch {
4933100ebe3SStefano Zampini   PetscFunctionBegin;
4943100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
4954f572ea9SToby Isaac   PetscAssertPointer(is, 2);
496cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetPrimalVerticesIS_C", (PC, IS *), (pc, is));
4973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4983100ebe3SStefano Zampini }
4993100ebe3SStefano Zampini 
PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc,IS PrimalVertices)500d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
501d71ae5a4SJacob Faibussowitsch {
502674ae819SStefano Zampini   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
50356282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
5041e6b0712SBarry Smith 
505674ae819SStefano Zampini   PetscFunctionBegin;
5069566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)PrimalVertices));
50748a46eb9SPierre Jolivet   if (pcbddc->user_primal_vertices_local) PetscCall(ISEqual(PrimalVertices, pcbddc->user_primal_vertices_local, &isequal));
5089566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices));
5099566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local));
51030368db7SStefano Zampini   pcbddc->user_primal_vertices_local = PrimalVertices;
51156282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
5123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
513674ae819SStefano Zampini }
5143100ebe3SStefano Zampini 
515674ae819SStefano Zampini /*@
516f1580f4eSBarry Smith   PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in `PCBDDC`
517674ae819SStefano Zampini 
51817eb1463SStefano Zampini   Collective
519674ae819SStefano Zampini 
520674ae819SStefano Zampini   Input Parameters:
521674ae819SStefano Zampini + pc             - the preconditioning context
52217eb1463SStefano Zampini - PrimalVertices - index set of primal vertices in local numbering (can be empty)
523674ae819SStefano Zampini 
524674ae819SStefano Zampini   Level: intermediate
525674ae819SStefano Zampini 
526562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesLocalIS()`
527674ae819SStefano Zampini @*/
PCBDDCSetPrimalVerticesLocalIS(PC pc,IS PrimalVertices)528d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
529d71ae5a4SJacob Faibussowitsch {
530674ae819SStefano Zampini   PetscFunctionBegin;
531674ae819SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
532674ae819SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices, IS_CLASSID, 2);
53317eb1463SStefano Zampini   PetscCheckSameComm(pc, 1, PrimalVertices, 2);
534cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetPrimalVerticesLocalIS_C", (PC, IS), (pc, PrimalVertices));
5353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
536674ae819SStefano Zampini }
5372d505d7fSStefano Zampini 
PCBDDCGetPrimalVerticesLocalIS_BDDC(PC pc,IS * is)538d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetPrimalVerticesLocalIS_BDDC(PC pc, IS *is)
539d71ae5a4SJacob Faibussowitsch {
5403100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
5413100ebe3SStefano Zampini 
5423100ebe3SStefano Zampini   PetscFunctionBegin;
5433100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices_local;
5443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5453100ebe3SStefano Zampini }
5463100ebe3SStefano Zampini 
5473100ebe3SStefano Zampini /*@
548f1580f4eSBarry Smith   PCBDDCGetPrimalVerticesLocalIS - Get user defined primal vertices set with `PCBDDCSetPrimalVerticesLocalIS()`
5493100ebe3SStefano Zampini 
5503100ebe3SStefano Zampini   Collective
5513100ebe3SStefano Zampini 
552f1580f4eSBarry Smith   Input Parameter:
5533100ebe3SStefano Zampini . pc - the preconditioning context
5543100ebe3SStefano Zampini 
555f1580f4eSBarry Smith   Output Parameter:
55620f4b53cSBarry Smith . is - index set of primal vertices in local numbering (`NULL` if not set)
5573100ebe3SStefano Zampini 
5583100ebe3SStefano Zampini   Level: intermediate
5593100ebe3SStefano Zampini 
560562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`
5613100ebe3SStefano Zampini @*/
PCBDDCGetPrimalVerticesLocalIS(PC pc,IS * is)562d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetPrimalVerticesLocalIS(PC pc, IS *is)
563d71ae5a4SJacob Faibussowitsch {
5643100ebe3SStefano Zampini   PetscFunctionBegin;
5653100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
5664f572ea9SToby Isaac   PetscAssertPointer(is, 2);
567cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetPrimalVerticesLocalIS_C", (PC, IS *), (pc, is));
5683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5693100ebe3SStefano Zampini }
5703100ebe3SStefano Zampini 
PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k)571d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc, PetscInt k)
572d71ae5a4SJacob Faibussowitsch {
5734fad6a16SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
5744fad6a16SStefano Zampini 
5754fad6a16SStefano Zampini   PetscFunctionBegin;
5764fad6a16SStefano Zampini   pcbddc->coarsening_ratio = k;
5773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5784fad6a16SStefano Zampini }
5791e6b0712SBarry Smith 
5804fad6a16SStefano Zampini /*@
58198ad52f2SBarry Smith   PCBDDCSetCoarseningRatio - Set coarsening ratio used in the multi-level version of `PCBDDC`
5824fad6a16SStefano Zampini 
58320f4b53cSBarry Smith   Logically Collective
5844fad6a16SStefano Zampini 
5854fad6a16SStefano Zampini   Input Parameters:
5864fad6a16SStefano Zampini + pc - the preconditioning context
58728509bceSStefano Zampini - k  - coarsening ratio (H/h at the coarser level)
5884fad6a16SStefano Zampini 
589f1580f4eSBarry Smith   Options Database Key:
59098ad52f2SBarry Smith . -pc_bddc_coarsening_ratio <int> - Set the coarsening ratio used in multi-level coarsening
5914fad6a16SStefano Zampini 
5924fad6a16SStefano Zampini   Level: intermediate
5934fad6a16SStefano Zampini 
594f1580f4eSBarry Smith   Note:
59520f4b53cSBarry Smith   Approximately `k` subdomains at the finer level will be aggregated into a single subdomain at the coarser level
5964fad6a16SStefano Zampini 
597562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetLevels()`
5984fad6a16SStefano Zampini @*/
PCBDDCSetCoarseningRatio(PC pc,PetscInt k)599d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetCoarseningRatio(PC pc, PetscInt k)
600d71ae5a4SJacob Faibussowitsch {
6014fad6a16SStefano Zampini   PetscFunctionBegin;
6024fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
6032b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc, k, 2);
604cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetCoarseningRatio_C", (PC, PetscInt), (pc, k));
6053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6064fad6a16SStefano Zampini }
6072b510759SStefano Zampini 
608b8ffe317SStefano Zampini /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */
PCBDDCSetUseExactDirichlet_BDDC(PC pc,PetscBool flg)609d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc, PetscBool flg)
610d71ae5a4SJacob Faibussowitsch {
611b8ffe317SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
612b8ffe317SStefano Zampini 
613b8ffe317SStefano Zampini   PetscFunctionBegin;
61485c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = flg;
6153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
616b8ffe317SStefano Zampini }
617b8ffe317SStefano Zampini 
PCBDDCSetUseExactDirichlet(PC pc,PetscBool flg)618d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc, PetscBool flg)
619d71ae5a4SJacob Faibussowitsch {
6202b510759SStefano Zampini   PetscFunctionBegin;
6212b510759SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
622b8ffe317SStefano Zampini   PetscValidLogicalCollectiveBool(pc, flg, 2);
623cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetUseExactDirichlet_C", (PC, PetscBool), (pc, flg));
6243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6252b510759SStefano Zampini }
6261e6b0712SBarry Smith 
PCBDDCSetLevel_BDDC(PC pc,PetscInt level)627d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc, PetscInt level)
628d71ae5a4SJacob Faibussowitsch {
6294fad6a16SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
6304fad6a16SStefano Zampini 
6314fad6a16SStefano Zampini   PetscFunctionBegin;
6322b510759SStefano Zampini   pcbddc->current_level = level;
6333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6344fad6a16SStefano Zampini }
6351e6b0712SBarry Smith 
PCBDDCSetLevel(PC pc,PetscInt level)636d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetLevel(PC pc, PetscInt level)
637d71ae5a4SJacob Faibussowitsch {
638b8ffe317SStefano Zampini   PetscFunctionBegin;
639b8ffe317SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
640b8ffe317SStefano Zampini   PetscValidLogicalCollectiveInt(pc, level, 2);
641cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetLevel_C", (PC, PetscInt), (pc, level));
6423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
643b8ffe317SStefano Zampini }
644b8ffe317SStefano Zampini 
PCBDDCSetLevels_BDDC(PC pc,PetscInt levels)645d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc, PetscInt levels)
646d71ae5a4SJacob Faibussowitsch {
6472b510759SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
6482b510759SStefano Zampini 
6492b510759SStefano Zampini   PetscFunctionBegin;
6507827d75bSBarry 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);
6512b510759SStefano Zampini   pcbddc->max_levels = levels;
6523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6532b510759SStefano Zampini }
6542b510759SStefano Zampini 
6554fad6a16SStefano Zampini /*@
656f1580f4eSBarry Smith   PCBDDCSetLevels - Sets the maximum number of additional levels allowed for multilevel `PCBDDC`
6574fad6a16SStefano Zampini 
65820f4b53cSBarry Smith   Logically Collective
6594fad6a16SStefano Zampini 
6604fad6a16SStefano Zampini   Input Parameters:
6614fad6a16SStefano Zampini + pc     - the preconditioning context
66237ebbdf7SStefano Zampini - levels - the maximum number of levels
6634fad6a16SStefano Zampini 
664f1580f4eSBarry Smith   Options Database Key:
66567b8a455SSatish Balay . -pc_bddc_levels <int> - Set maximum number of levels for multilevel
6664fad6a16SStefano Zampini 
6674fad6a16SStefano Zampini   Level: intermediate
6684fad6a16SStefano Zampini 
669f1580f4eSBarry Smith   Note:
67098ad52f2SBarry Smith   The default value is 0, that gives the classical two-levels BDDC algorithm
6714fad6a16SStefano Zampini 
672562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetCoarseningRatio()`
6734fad6a16SStefano Zampini @*/
PCBDDCSetLevels(PC pc,PetscInt levels)674d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetLevels(PC pc, PetscInt levels)
675d71ae5a4SJacob Faibussowitsch {
6764fad6a16SStefano Zampini   PetscFunctionBegin;
6774fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
6782b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc, levels, 2);
679cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetLevels_C", (PC, PetscInt), (pc, levels));
6803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6814fad6a16SStefano Zampini }
6821e6b0712SBarry Smith 
PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)683d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc, IS DirichletBoundaries)
684d71ae5a4SJacob Faibussowitsch {
6853b03a366Sstefano_zampini   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
68656282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
6873b03a366Sstefano_zampini 
6883b03a366Sstefano_zampini   PetscFunctionBegin;
6899566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)DirichletBoundaries));
69048a46eb9SPierre Jolivet   if (pcbddc->DirichletBoundaries) PetscCall(ISEqual(DirichletBoundaries, pcbddc->DirichletBoundaries, &isequal));
691a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
6929566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal));
6939566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundaries));
69436e030ebSStefano Zampini   pcbddc->DirichletBoundaries = DirichletBoundaries;
69556282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
6963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6973b03a366Sstefano_zampini }
6981e6b0712SBarry Smith 
6993b03a366Sstefano_zampini /*@
70098ad52f2SBarry Smith   PCBDDCSetDirichletBoundaries - Set the `IS` defining Dirichlet boundaries for the global problem.
7013b03a366Sstefano_zampini 
702785d1243SStefano Zampini   Collective
7033b03a366Sstefano_zampini 
7043b03a366Sstefano_zampini   Input Parameters:
7053b03a366Sstefano_zampini + pc                  - the preconditioning context
70620f4b53cSBarry Smith - DirichletBoundaries - parallel `IS` defining the Dirichlet boundaries
7073b03a366Sstefano_zampini 
7083b03a366Sstefano_zampini   Level: intermediate
7093b03a366Sstefano_zampini 
710f1580f4eSBarry Smith   Note:
711f1580f4eSBarry Smith   Provide the information if you used `MatZeroRows()` or `MatZeroRowsColumns()`. Any process can list any global node
7123b03a366Sstefano_zampini 
713562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDirichletBoundariesLocal()`, `MatZeroRows()`, `MatZeroRowsColumns()`
7143b03a366Sstefano_zampini @*/
PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)715d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc, IS DirichletBoundaries)
716d71ae5a4SJacob Faibussowitsch {
7173b03a366Sstefano_zampini   PetscFunctionBegin;
7183b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
719674ae819SStefano Zampini   PetscValidHeaderSpecific(DirichletBoundaries, IS_CLASSID, 2);
720785d1243SStefano Zampini   PetscCheckSameComm(pc, 1, DirichletBoundaries, 2);
721cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDirichletBoundaries_C", (PC, IS), (pc, DirichletBoundaries));
7223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7233b03a366Sstefano_zampini }
7241e6b0712SBarry Smith 
PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc,IS DirichletBoundaries)725d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc, IS DirichletBoundaries)
726d71ae5a4SJacob Faibussowitsch {
7273b03a366Sstefano_zampini   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
72856282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
7293b03a366Sstefano_zampini 
7303b03a366Sstefano_zampini   PetscFunctionBegin;
7319566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)DirichletBoundaries));
73248a46eb9SPierre Jolivet   if (pcbddc->DirichletBoundariesLocal) PetscCall(ISEqual(DirichletBoundaries, pcbddc->DirichletBoundariesLocal, &isequal));
733a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
7349566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal));
7359566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundaries));
736785d1243SStefano Zampini   pcbddc->DirichletBoundariesLocal = DirichletBoundaries;
73756282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7393b03a366Sstefano_zampini }
7403b03a366Sstefano_zampini 
7413b03a366Sstefano_zampini /*@
74298ad52f2SBarry Smith   PCBDDCSetDirichletBoundariesLocal - Set the `IS` defining Dirichlet boundaries for the global problem in local ordering.
7433b03a366Sstefano_zampini 
744785d1243SStefano Zampini   Collective
7453b03a366Sstefano_zampini 
7463b03a366Sstefano_zampini   Input Parameters:
7473b03a366Sstefano_zampini + pc                  - the preconditioning context
74820f4b53cSBarry Smith - DirichletBoundaries - parallel `IS` defining the Dirichlet boundaries (in local ordering)
7493b03a366Sstefano_zampini 
7503b03a366Sstefano_zampini   Level: intermediate
7513b03a366Sstefano_zampini 
752562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDirichletBoundaries()`, `MatZeroRows()`, `MatZeroRowsColumns()`
7533b03a366Sstefano_zampini @*/
PCBDDCSetDirichletBoundariesLocal(PC pc,IS DirichletBoundaries)754d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc, IS DirichletBoundaries)
755d71ae5a4SJacob Faibussowitsch {
7563b03a366Sstefano_zampini   PetscFunctionBegin;
7573b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
7583b03a366Sstefano_zampini   PetscValidHeaderSpecific(DirichletBoundaries, IS_CLASSID, 2);
75982ba6b80SStefano Zampini   PetscCheckSameComm(pc, 1, DirichletBoundaries, 2);
760cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDirichletBoundariesLocal_C", (PC, IS), (pc, DirichletBoundaries));
7613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7623b03a366Sstefano_zampini }
7633b03a366Sstefano_zampini 
PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)764d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc, IS NeumannBoundaries)
765d71ae5a4SJacob Faibussowitsch {
7660c7d97c5SJed Brown   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
76756282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
7680c7d97c5SJed Brown 
7690c7d97c5SJed Brown   PetscFunctionBegin;
7709566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries));
77148a46eb9SPierre Jolivet   if (pcbddc->NeumannBoundaries) PetscCall(ISEqual(NeumannBoundaries, pcbddc->NeumannBoundaries, &isequal));
772a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
7739566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal));
7749566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundaries));
77536e030ebSStefano Zampini   pcbddc->NeumannBoundaries = NeumannBoundaries;
77656282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7780c7d97c5SJed Brown }
7791e6b0712SBarry Smith 
78057527edcSJed Brown /*@
78198ad52f2SBarry Smith   PCBDDCSetNeumannBoundaries - Set the `IS` defining Neumann boundaries for the global problem.
78257527edcSJed Brown 
783c3339decSBarry Smith   Collective
78457527edcSJed Brown 
78557527edcSJed Brown   Input Parameters:
78657527edcSJed Brown + pc                - the preconditioning context
78720f4b53cSBarry Smith - NeumannBoundaries - parallel `IS` defining the Neumann boundaries
78857527edcSJed Brown 
78957527edcSJed Brown   Level: intermediate
79057527edcSJed Brown 
791f1580f4eSBarry Smith   Note:
7920f202f7eSStefano Zampini   Any process can list any global node
79357527edcSJed Brown 
794562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetNeumannBoundariesLocal()`
79557527edcSJed Brown @*/
PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)796d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc, IS NeumannBoundaries)
797d71ae5a4SJacob Faibussowitsch {
7980c7d97c5SJed Brown   PetscFunctionBegin;
7990c7d97c5SJed Brown   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
800674ae819SStefano Zampini   PetscValidHeaderSpecific(NeumannBoundaries, IS_CLASSID, 2);
801785d1243SStefano Zampini   PetscCheckSameComm(pc, 1, NeumannBoundaries, 2);
802cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetNeumannBoundaries_C", (PC, IS), (pc, NeumannBoundaries));
8033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
80453cdbc3dSStefano Zampini }
8051e6b0712SBarry Smith 
PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc,IS NeumannBoundaries)806d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc, IS NeumannBoundaries)
807d71ae5a4SJacob Faibussowitsch {
8080c7d97c5SJed Brown   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
80956282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
8100c7d97c5SJed Brown 
8110c7d97c5SJed Brown   PetscFunctionBegin;
8129566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries));
81348a46eb9SPierre Jolivet   if (pcbddc->NeumannBoundariesLocal) PetscCall(ISEqual(NeumannBoundaries, pcbddc->NeumannBoundariesLocal, &isequal));
814a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
8159566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal));
8169566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundaries));
817785d1243SStefano Zampini   pcbddc->NeumannBoundariesLocal = NeumannBoundaries;
81856282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
8193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8200c7d97c5SJed Brown }
8210c7d97c5SJed Brown 
8220c7d97c5SJed Brown /*@
82398ad52f2SBarry Smith   PCBDDCSetNeumannBoundariesLocal - Set the `IS` defining Neumann boundaries for the global problem in local ordering.
8240c7d97c5SJed Brown 
825785d1243SStefano Zampini   Collective
8260c7d97c5SJed Brown 
8270c7d97c5SJed Brown   Input Parameters:
8280c7d97c5SJed Brown + pc                - the preconditioning context
82920f4b53cSBarry Smith - NeumannBoundaries - parallel `IS` defining the subdomain part of Neumann boundaries (in local ordering)
8300c7d97c5SJed Brown 
8310c7d97c5SJed Brown   Level: intermediate
8320c7d97c5SJed Brown 
833562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCGetDirichletBoundaries()`
8340c7d97c5SJed Brown @*/
PCBDDCSetNeumannBoundariesLocal(PC pc,IS NeumannBoundaries)835d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc, IS NeumannBoundaries)
836d71ae5a4SJacob Faibussowitsch {
8370c7d97c5SJed Brown   PetscFunctionBegin;
8380c7d97c5SJed Brown   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
8390c7d97c5SJed Brown   PetscValidHeaderSpecific(NeumannBoundaries, IS_CLASSID, 2);
84082ba6b80SStefano Zampini   PetscCheckSameComm(pc, 1, NeumannBoundaries, 2);
841cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetNeumannBoundariesLocal_C", (PC, IS), (pc, NeumannBoundaries));
8423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
84353cdbc3dSStefano Zampini }
84453cdbc3dSStefano Zampini 
PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS * DirichletBoundaries)845d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc, IS *DirichletBoundaries)
846d71ae5a4SJacob Faibussowitsch {
847da1bb401SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
848da1bb401SStefano Zampini 
849da1bb401SStefano Zampini   PetscFunctionBegin;
850da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
8513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
852da1bb401SStefano Zampini }
8531e6b0712SBarry Smith 
854da1bb401SStefano Zampini /*@
855f1580f4eSBarry Smith   PCBDDCGetDirichletBoundaries - Get parallel `IS` for Dirichlet boundaries
856da1bb401SStefano Zampini 
857785d1243SStefano Zampini   Collective
858785d1243SStefano Zampini 
859f1580f4eSBarry Smith   Input Parameter:
860785d1243SStefano Zampini . pc - the preconditioning context
861785d1243SStefano Zampini 
862f1580f4eSBarry Smith   Output Parameter:
863785d1243SStefano Zampini . DirichletBoundaries - index set defining the Dirichlet boundaries
864785d1243SStefano Zampini 
865785d1243SStefano Zampini   Level: intermediate
866785d1243SStefano Zampini 
867f1580f4eSBarry Smith   Note:
868f1580f4eSBarry Smith   The `IS` returned (if any) is the same passed in earlier by the user with `PCBDDCSetDirichletBoundaries()`
869785d1243SStefano Zampini 
870562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDirichletBoundaries()`
871785d1243SStefano Zampini @*/
PCBDDCGetDirichletBoundaries(PC pc,IS * DirichletBoundaries)872d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc, IS *DirichletBoundaries)
873d71ae5a4SJacob Faibussowitsch {
874785d1243SStefano Zampini   PetscFunctionBegin;
875785d1243SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
876cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetDirichletBoundaries_C", (PC, IS *), (pc, DirichletBoundaries));
8773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
878785d1243SStefano Zampini }
879785d1243SStefano Zampini 
PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc,IS * DirichletBoundaries)880d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc, IS *DirichletBoundaries)
881d71ae5a4SJacob Faibussowitsch {
882785d1243SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
883785d1243SStefano Zampini 
884785d1243SStefano Zampini   PetscFunctionBegin;
885785d1243SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundariesLocal;
8863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
887785d1243SStefano Zampini }
888785d1243SStefano Zampini 
889da1bb401SStefano Zampini /*@
890f1580f4eSBarry Smith   PCBDDCGetDirichletBoundariesLocal - Get parallel `IS` for Dirichlet boundaries (in local ordering)
891da1bb401SStefano Zampini 
892785d1243SStefano Zampini   Collective
893da1bb401SStefano Zampini 
894f1580f4eSBarry Smith   Input Parameter:
89528509bceSStefano Zampini . pc - the preconditioning context
896da1bb401SStefano Zampini 
897f1580f4eSBarry Smith   Output Parameter:
89828509bceSStefano Zampini . DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
899da1bb401SStefano Zampini 
900da1bb401SStefano Zampini   Level: intermediate
901da1bb401SStefano Zampini 
902f1580f4eSBarry Smith   Note:
903f1580f4eSBarry Smith   The `IS` returned could be the same passed in earlier by the user (if provided with `PCBDDCSetDirichletBoundariesLocal()`)
904f1580f4eSBarry Smith   or a global-to-local map of the global `IS` (if provided with `PCBDDCSetDirichletBoundaries()`).
905f1580f4eSBarry Smith   In the latter case, the `IS` will be available only after `PCSetUp()`.
906da1bb401SStefano Zampini 
907562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCGetDirichletBoundaries()`, `PCBDDCSetDirichletBoundaries()`
908da1bb401SStefano Zampini @*/
PCBDDCGetDirichletBoundariesLocal(PC pc,IS * DirichletBoundaries)909d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc, IS *DirichletBoundaries)
910d71ae5a4SJacob Faibussowitsch {
911da1bb401SStefano Zampini   PetscFunctionBegin;
912da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
913cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetDirichletBoundariesLocal_C", (PC, IS *), (pc, DirichletBoundaries));
9143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
915da1bb401SStefano Zampini }
9161e6b0712SBarry Smith 
PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS * NeumannBoundaries)917d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc, IS *NeumannBoundaries)
918d71ae5a4SJacob Faibussowitsch {
91953cdbc3dSStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
92053cdbc3dSStefano Zampini 
92153cdbc3dSStefano Zampini   PetscFunctionBegin;
92253cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
9233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
92453cdbc3dSStefano Zampini }
9251e6b0712SBarry Smith 
92653cdbc3dSStefano Zampini /*@
927f1580f4eSBarry Smith   PCBDDCGetNeumannBoundaries - Get parallel `IS` for Neumann boundaries
92853cdbc3dSStefano Zampini 
929f1580f4eSBarry Smith   Not Collective
930785d1243SStefano Zampini 
931f1580f4eSBarry Smith   Input Parameter:
932785d1243SStefano Zampini . pc - the preconditioning context
933785d1243SStefano Zampini 
934f1580f4eSBarry Smith   Output Parameter:
935785d1243SStefano Zampini . NeumannBoundaries - index set defining the Neumann boundaries
936785d1243SStefano Zampini 
937785d1243SStefano Zampini   Level: intermediate
938785d1243SStefano Zampini 
939f1580f4eSBarry Smith   Note:
940f1580f4eSBarry Smith   The `IS` returned (if any) is the same passed in earlier by the user with `PCBDDCSetNeumannBoundaries()`
941785d1243SStefano Zampini 
942562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCGetDirichletBoundaries()`, `PCBDDCSetDirichletBoundaries()`
943785d1243SStefano Zampini @*/
PCBDDCGetNeumannBoundaries(PC pc,IS * NeumannBoundaries)944d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc, IS *NeumannBoundaries)
945d71ae5a4SJacob Faibussowitsch {
946785d1243SStefano Zampini   PetscFunctionBegin;
947785d1243SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
948cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetNeumannBoundaries_C", (PC, IS *), (pc, NeumannBoundaries));
9493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
950785d1243SStefano Zampini }
951785d1243SStefano Zampini 
PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc,IS * NeumannBoundaries)952d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc, IS *NeumannBoundaries)
953d71ae5a4SJacob Faibussowitsch {
954785d1243SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
955785d1243SStefano Zampini 
956785d1243SStefano Zampini   PetscFunctionBegin;
957785d1243SStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundariesLocal;
9583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
959785d1243SStefano Zampini }
960785d1243SStefano Zampini 
96153cdbc3dSStefano Zampini /*@
962f1580f4eSBarry Smith   PCBDDCGetNeumannBoundariesLocal - Get parallel `IS` for Neumann boundaries (in local ordering)
96353cdbc3dSStefano Zampini 
964f1580f4eSBarry Smith   Not Collective
96553cdbc3dSStefano Zampini 
966f1580f4eSBarry Smith   Input Parameter:
96728509bceSStefano Zampini . pc - the preconditioning context
96853cdbc3dSStefano Zampini 
969f1580f4eSBarry Smith   Output Parameter:
97028509bceSStefano Zampini . NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
97153cdbc3dSStefano Zampini 
97253cdbc3dSStefano Zampini   Level: intermediate
97353cdbc3dSStefano Zampini 
974f1580f4eSBarry Smith   Note:
975f1580f4eSBarry Smith   The `IS` returned could be the same passed in earlier by the user (if provided with `PCBDDCSetNeumannBoundariesLocal()`
976f1580f4eSBarry Smith   or a global-to-local map of the global `IS` (if provided with `PCBDDCSetNeumannBoundaries()`).
977f1580f4eSBarry Smith   In the latter case, the `IS` will be available after `PCSetUp()`.
97853cdbc3dSStefano Zampini 
979f8d70eaaSPierre Jolivet .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCSetNeumannBoundariesLocal()`, `PCBDDCGetNeumannBoundaries()`
98053cdbc3dSStefano Zampini @*/
PCBDDCGetNeumannBoundariesLocal(PC pc,IS * NeumannBoundaries)981d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc, IS *NeumannBoundaries)
982d71ae5a4SJacob Faibussowitsch {
98353cdbc3dSStefano Zampini   PetscFunctionBegin;
98453cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
985cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetNeumannBoundariesLocal_C", (PC, IS *), (pc, NeumannBoundaries));
9863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9870c7d97c5SJed Brown }
9881e6b0712SBarry Smith 
PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[],PetscCopyMode copymode)989d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs, const PetscInt xadj[], const PetscInt adjncy[], PetscCopyMode copymode)
990d71ae5a4SJacob Faibussowitsch {
99136e030ebSStefano Zampini   PC_BDDC    *pcbddc    = (PC_BDDC *)pc->data;
992da1bb401SStefano Zampini   PCBDDCGraph mat_graph = pcbddc->mat_graph;
99356282151SStefano Zampini   PetscBool   same_data = PETSC_FALSE;
99436e030ebSStefano Zampini 
99536e030ebSStefano Zampini   PetscFunctionBegin;
9968687889aSStefano Zampini   if (!nvtxs) {
99704194a47SStefano Zampini     if (copymode == PETSC_OWN_POINTER) {
9989566063dSJacob Faibussowitsch       PetscCall(PetscFree(xadj));
9999566063dSJacob Faibussowitsch       PetscCall(PetscFree(adjncy));
100004194a47SStefano Zampini     }
10019566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphResetCSR(mat_graph));
10023ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
10038687889aSStefano Zampini   }
100466da6bd7Sstefano_zampini   if (mat_graph->nvtxs == nvtxs && mat_graph->freecsr) { /* we own the data */
100556282151SStefano Zampini     if (mat_graph->xadj == xadj && mat_graph->adjncy == adjncy) same_data = PETSC_TRUE;
100656282151SStefano Zampini     if (!same_data && mat_graph->xadj[nvtxs] == xadj[nvtxs]) {
10079566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(xadj, mat_graph->xadj, nvtxs + 1, &same_data));
100848a46eb9SPierre Jolivet       if (same_data) PetscCall(PetscArraycmp(adjncy, mat_graph->adjncy, xadj[nvtxs], &same_data));
100956282151SStefano Zampini     }
101056282151SStefano Zampini   }
101156282151SStefano Zampini   if (!same_data) {
1012674ae819SStefano Zampini     /* free old CSR */
10139566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphResetCSR(mat_graph));
1014674ae819SStefano Zampini     /* get CSR into graph structure */
1015da1bb401SStefano Zampini     if (copymode == PETSC_COPY_VALUES) {
10169566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvtxs + 1, &mat_graph->xadj));
10179566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(xadj[nvtxs], &mat_graph->adjncy));
10189566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(mat_graph->xadj, xadj, nvtxs + 1));
10199566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(mat_graph->adjncy, adjncy, xadj[nvtxs]));
1020a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1021da1bb401SStefano Zampini     } else if (copymode == PETSC_OWN_POINTER) {
10221a83f524SJed Brown       mat_graph->xadj    = (PetscInt *)xadj;
10231a83f524SJed Brown       mat_graph->adjncy  = (PetscInt *)adjncy;
1024a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1025a1dbd327SStefano Zampini     } else if (copymode == PETSC_USE_POINTER) {
1026a1dbd327SStefano Zampini       mat_graph->xadj    = (PetscInt *)xadj;
1027a1dbd327SStefano Zampini       mat_graph->adjncy  = (PetscInt *)adjncy;
1028a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_FALSE;
102963a3b9bcSJacob Faibussowitsch     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported copy mode %d", copymode);
1030575ad6abSStefano Zampini     mat_graph->nvtxs_csr         = nvtxs;
103156282151SStefano Zampini     pcbddc->recompute_topography = PETSC_TRUE;
103256282151SStefano Zampini   }
10333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
103436e030ebSStefano Zampini }
10351e6b0712SBarry Smith 
103636e030ebSStefano Zampini /*@
103754fffbccSStefano Zampini   PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local degrees of freedom.
103836e030ebSStefano Zampini 
103936e030ebSStefano Zampini   Not collective
104036e030ebSStefano Zampini 
104136e030ebSStefano Zampini   Input Parameters:
104254fffbccSStefano Zampini + pc       - the preconditioning context.
104354fffbccSStefano Zampini . nvtxs    - number of local vertices of the graph (i.e., the number of local dofs).
104404c3f3b8SBarry Smith . xadj     - CSR format row pointers for the connectivity of the dofs
104504c3f3b8SBarry Smith . adjncy   - CSR format column pointers for the connectivity of the dofs
1046f1580f4eSBarry Smith - copymode - supported modes are `PETSC_COPY_VALUES`, `PETSC_USE_POINTER` or `PETSC_OWN_POINTER`.
104736e030ebSStefano Zampini 
104836e030ebSStefano Zampini   Level: intermediate
104936e030ebSStefano Zampini 
1050f1580f4eSBarry Smith   Note:
105195452b02SPatrick Sanan   A dof is considered connected with all local dofs if xadj[dof+1]-xadj[dof] == 1 and adjncy[xadj[dof]] is negative.
105236e030ebSStefano Zampini 
1053562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PetscCopyMode`
105436e030ebSStefano Zampini @*/
PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[],PetscCopyMode copymode)1055d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc, PetscInt nvtxs, const PetscInt xadj[], const PetscInt adjncy[], PetscCopyMode copymode)
1056d71ae5a4SJacob Faibussowitsch {
10570cd8b6e2SStefano Zampini   PetscBool f = PETSC_FALSE;
105836e030ebSStefano Zampini 
105936e030ebSStefano Zampini   PetscFunctionBegin;
106036e030ebSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
10618687889aSStefano Zampini   if (nvtxs) {
10624f572ea9SToby Isaac     PetscAssertPointer(xadj, 3);
10634f572ea9SToby Isaac     if (xadj[nvtxs]) PetscAssertPointer(adjncy, 4);
10648687889aSStefano Zampini   }
1065cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetLocalAdjacencyGraph_C", (PC, PetscInt, const PetscInt[], const PetscInt[], PetscCopyMode), (pc, nvtxs, xadj, adjncy, copymode));
1066575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
10670cd8b6e2SStefano Zampini   PetscCall(PetscObjectHasFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", &f));
1068575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
10699566063dSJacob Faibussowitsch     PetscCall(PetscFree(xadj));
10709566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjncy));
1071da1bb401SStefano Zampini   }
10723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
107336e030ebSStefano Zampini }
10741e6b0712SBarry Smith 
PCBDDCSetDofsSplittingLocal_BDDC(PC pc,PetscInt n_is,IS ISForDofs[])1075d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc, PetscInt n_is, IS ISForDofs[])
1076d71ae5a4SJacob Faibussowitsch {
107763602bcaSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC *)pc->data;
107863602bcaSStefano Zampini   PetscInt  i;
107956282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
108063602bcaSStefano Zampini 
108163602bcaSStefano Zampini   PetscFunctionBegin;
108256282151SStefano Zampini   if (pcbddc->n_ISForDofsLocal == n_is) {
108356282151SStefano Zampini     for (i = 0; i < n_is; i++) {
108456282151SStefano Zampini       PetscBool isequalt;
10859566063dSJacob Faibussowitsch       PetscCall(ISEqual(ISForDofs[i], pcbddc->ISForDofsLocal[i], &isequalt));
108656282151SStefano Zampini       if (!isequalt) break;
108756282151SStefano Zampini     }
108856282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
108956282151SStefano Zampini   }
109048a46eb9SPierre Jolivet   for (i = 0; i < n_is; i++) PetscCall(PetscObjectReference((PetscObject)ISForDofs[i]));
109163602bcaSStefano Zampini   /* Destroy ISes if they were already set */
109248a46eb9SPierre Jolivet   for (i = 0; i < pcbddc->n_ISForDofsLocal; i++) PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i]));
10939566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofsLocal));
1094a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
109548a46eb9SPierre Jolivet   for (i = 0; i < pcbddc->n_ISForDofs; i++) PetscCall(ISDestroy(&pcbddc->ISForDofs[i]));
10969566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofs));
109763602bcaSStefano Zampini   pcbddc->n_ISForDofs = 0;
109863602bcaSStefano Zampini   /* allocate space then set */
109948a46eb9SPierre Jolivet   if (n_is) PetscCall(PetscMalloc1(n_is, &pcbddc->ISForDofsLocal));
1100ad540459SPierre Jolivet   for (i = 0; i < n_is; i++) pcbddc->ISForDofsLocal[i] = ISForDofs[i];
110163602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = n_is;
110263602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
110356282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
11043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
110563602bcaSStefano Zampini }
110663602bcaSStefano Zampini 
110763602bcaSStefano Zampini /*@
110898ad52f2SBarry Smith   PCBDDCSetDofsSplittingLocal - Set the `IS` defining fields of the local subdomain matrix
110963602bcaSStefano Zampini 
111063602bcaSStefano Zampini   Collective
111163602bcaSStefano Zampini 
111263602bcaSStefano Zampini   Input Parameters:
111363602bcaSStefano Zampini + pc        - the preconditioning context
111498ad52f2SBarry Smith . n_is      - number of index sets defining the fields, must be the same on all MPI processes
1115f1580f4eSBarry Smith - ISForDofs - array of `IS` describing the fields in local ordering
111663602bcaSStefano Zampini 
111763602bcaSStefano Zampini   Level: intermediate
111863602bcaSStefano Zampini 
1119f1580f4eSBarry Smith   Note:
1120feefa0e1SJacob Faibussowitsch   Not all nodes need to be listed, unlisted nodes will belong to the complement field.
112163602bcaSStefano Zampini 
1122562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDofsSplitting()`
112363602bcaSStefano Zampini @*/
PCBDDCSetDofsSplittingLocal(PC pc,PetscInt n_is,IS ISForDofs[])1124d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc, PetscInt n_is, IS ISForDofs[])
1125d71ae5a4SJacob Faibussowitsch {
112663602bcaSStefano Zampini   PetscInt i;
112763602bcaSStefano Zampini 
112863602bcaSStefano Zampini   PetscFunctionBegin;
112963602bcaSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
113063602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc, n_is, 2);
113163602bcaSStefano Zampini   for (i = 0; i < n_is; i++) {
113263602bcaSStefano Zampini     PetscCheckSameComm(pc, 1, ISForDofs[i], 3);
113363602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i], IS_CLASSID, 3);
113463602bcaSStefano Zampini   }
1135cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDofsSplittingLocal_C", (PC, PetscInt, IS[]), (pc, n_is, ISForDofs));
11363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
113763602bcaSStefano Zampini }
113863602bcaSStefano Zampini 
PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is,IS ISForDofs[])1139d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc, PetscInt n_is, IS ISForDofs[])
1140d71ae5a4SJacob Faibussowitsch {
11419c0446d6SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC *)pc->data;
11429c0446d6SStefano Zampini   PetscInt  i;
114356282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
11449c0446d6SStefano Zampini 
11459c0446d6SStefano Zampini   PetscFunctionBegin;
114656282151SStefano Zampini   if (pcbddc->n_ISForDofs == n_is) {
114756282151SStefano Zampini     for (i = 0; i < n_is; i++) {
114856282151SStefano Zampini       PetscBool isequalt;
11499566063dSJacob Faibussowitsch       PetscCall(ISEqual(ISForDofs[i], pcbddc->ISForDofs[i], &isequalt));
115056282151SStefano Zampini       if (!isequalt) break;
115156282151SStefano Zampini     }
115256282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
115356282151SStefano Zampini   }
115448a46eb9SPierre Jolivet   for (i = 0; i < n_is; i++) PetscCall(PetscObjectReference((PetscObject)ISForDofs[i]));
1155da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
115648a46eb9SPierre Jolivet   for (i = 0; i < pcbddc->n_ISForDofs; i++) PetscCall(ISDestroy(&pcbddc->ISForDofs[i]));
11579566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofs));
1158a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
115948a46eb9SPierre Jolivet   for (i = 0; i < pcbddc->n_ISForDofsLocal; i++) PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i]));
11609566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofsLocal));
116163602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = 0;
1162da1bb401SStefano Zampini   /* allocate space then set */
116348a46eb9SPierre Jolivet   if (n_is) PetscCall(PetscMalloc1(n_is, &pcbddc->ISForDofs));
1164ad540459SPierre Jolivet   for (i = 0; i < n_is; i++) pcbddc->ISForDofs[i] = ISForDofs[i];
11659c0446d6SStefano Zampini   pcbddc->n_ISForDofs = n_is;
116663602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
116756282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
11683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11699c0446d6SStefano Zampini }
11701e6b0712SBarry Smith 
11719c0446d6SStefano Zampini /*@
117298ad52f2SBarry Smith   PCBDDCSetDofsSplitting - Set the `IS` defining fields of the global matrix
11739c0446d6SStefano Zampini 
117463602bcaSStefano Zampini   Collective
11759c0446d6SStefano Zampini 
11769c0446d6SStefano Zampini   Input Parameters:
11779c0446d6SStefano Zampini + pc        - the preconditioning context
11780f202f7eSStefano Zampini . n_is      - number of index sets defining the fields
117998ad52f2SBarry Smith - ISForDofs - array of `IS` describing the fields in global ordering
11809c0446d6SStefano Zampini 
11819c0446d6SStefano Zampini   Level: intermediate
11829c0446d6SStefano Zampini 
1183f1580f4eSBarry Smith   Note:
11840f202f7eSStefano Zampini   Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
11859c0446d6SStefano Zampini 
1186562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDofsSplittingLocal()`
11879c0446d6SStefano Zampini @*/
PCBDDCSetDofsSplitting(PC pc,PetscInt n_is,IS ISForDofs[])1188d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDofsSplitting(PC pc, PetscInt n_is, IS ISForDofs[])
1189d71ae5a4SJacob Faibussowitsch {
11902b510759SStefano Zampini   PetscInt i;
11919c0446d6SStefano Zampini 
11929c0446d6SStefano Zampini   PetscFunctionBegin;
11939c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
119463602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc, n_is, 2);
11952b510759SStefano Zampini   for (i = 0; i < n_is; i++) {
119663602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i], IS_CLASSID, 3);
1197a011d5a7Sstefano_zampini     PetscCheckSameComm(pc, 1, ISForDofs[i], 3);
11982b510759SStefano Zampini   }
1199cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDofsSplitting_C", (PC, PetscInt, IS[]), (pc, n_is, ISForDofs));
12003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12019c0446d6SStefano Zampini }
1202906d46d4SStefano Zampini 
PCPreSolve_BDDC(PC pc,KSP ksp,Vec rhs,Vec x)1203d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1204d71ae5a4SJacob Faibussowitsch {
1205534831adSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC *)pc->data;
1206f4f49eeaSPierre Jolivet   PC_IS    *pcis   = (PC_IS *)pc->data;
12073972b0daSStefano Zampini   Vec       used_vec;
1208fcb54b1cSPierre Jolivet   PetscBool iscg, save_rhs = PETSC_TRUE, benign_correction_computed;
1209534831adSStefano Zampini 
1210534831adSStefano Zampini   PetscFunctionBegin;
12111f4df5f7SStefano Zampini   /* if we are working with CG, one dirichlet solve can be avoided during Krylov iterations */
121285c4d303SStefano Zampini   if (ksp) {
1213fcb54b1cSPierre Jolivet     PetscCall(PetscObjectTypeCompareAny((PetscObject)ksp, &iscg, KSPCG, KSPGROPPCG, KSPPIPECG, KSPPIPELCG, KSPPIPECGRR, ""));
121448a46eb9SPierre Jolivet     if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || !iscg || pc->mat != pc->pmat) PetscCall(PCBDDCSetUseExactDirichlet(pc, PETSC_FALSE));
121585c4d303SStefano Zampini   }
121648a46eb9SPierre Jolivet   if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || pc->mat != pc->pmat) PetscCall(PCBDDCSetUseExactDirichlet(pc, PETSC_FALSE));
12171f4df5f7SStefano Zampini 
121885c4d303SStefano Zampini   /* Creates parallel work vectors used in presolve */
121948a46eb9SPierre Jolivet   if (!pcbddc->original_rhs) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->original_rhs));
122048a46eb9SPierre Jolivet   if (!pcbddc->temp_solution) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->temp_solution));
12218d00608fSStefano Zampini 
122227b6a85dSStefano Zampini   pcbddc->temp_solution_used = PETSC_FALSE;
12233972b0daSStefano Zampini   if (x) {
12249566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)x));
12253972b0daSStefano Zampini     used_vec = x;
12268d00608fSStefano Zampini   } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */
12279566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pcbddc->temp_solution));
12283972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
12299566063dSJacob Faibussowitsch     PetscCall(VecSet(used_vec, 0.0));
123027b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
12319566063dSJacob Faibussowitsch     PetscCall(VecCopy(rhs, pcbddc->original_rhs));
1232266e20e9SStefano Zampini     save_rhs                  = PETSC_FALSE;
1233266e20e9SStefano Zampini     pcbddc->eliminate_dirdofs = PETSC_TRUE;
12343972b0daSStefano Zampini   }
12358efcfb23SStefano Zampini 
12368efcfb23SStefano Zampini   /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */
12373972b0daSStefano Zampini   if (ksp) {
1238a0cb1b98SStefano Zampini     /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */
12399566063dSJacob Faibussowitsch     PetscCall(KSPGetInitialGuessNonzero(ksp, &pcbddc->ksp_guess_nonzero));
124048a46eb9SPierre Jolivet     if (!pcbddc->ksp_guess_nonzero) PetscCall(VecSet(used_vec, 0.0));
12413972b0daSStefano Zampini   }
12423308cffdSStefano Zampini 
12438d00608fSStefano Zampini   pcbddc->rhs_change = PETSC_FALSE;
12443972b0daSStefano Zampini   /* Take into account zeroed rows -> change rhs and store solution removed */
124570c64980SStefano Zampini   if (rhs && pcbddc->eliminate_dirdofs) {
12463975b054SStefano Zampini     IS dirIS = NULL;
12473975b054SStefano Zampini 
1248a07ea27aSStefano Zampini     /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */
12499566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph, &dirIS));
12503975b054SStefano Zampini     if (dirIS) {
1251906d46d4SStefano Zampini       Mat_IS            *matis = (Mat_IS *)pc->pmat->data;
1252785d1243SStefano Zampini       PetscInt           dirsize, i, *is_indices;
12532b095fd8SStefano Zampini       PetscScalar       *array_x;
12542b095fd8SStefano Zampini       const PetscScalar *array_diagonal;
1255785d1243SStefano Zampini 
12569566063dSJacob Faibussowitsch       PetscCall(MatGetDiagonal(pc->pmat, pcis->vec1_global));
12579566063dSJacob Faibussowitsch       PetscCall(VecPointwiseDivide(pcis->vec1_global, rhs, pcis->vec1_global));
12589566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_global, pcis->vec2_N, INSERT_VALUES, SCATTER_FORWARD));
12599566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_global, pcis->vec2_N, INSERT_VALUES, SCATTER_FORWARD));
12609566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx, used_vec, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD));
12619566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx, used_vec, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD));
12629566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(dirIS, &dirsize));
12639566063dSJacob Faibussowitsch       PetscCall(VecGetArray(pcis->vec1_N, &array_x));
12649566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(pcis->vec2_N, &array_diagonal));
12659566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(dirIS, (const PetscInt **)&is_indices));
12662fa5cd67SKarl Rupp       for (i = 0; i < dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
12679566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(dirIS, (const PetscInt **)&is_indices));
12689566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(pcis->vec2_N, &array_diagonal));
12699566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(pcis->vec1_N, &array_x));
12709566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_N, used_vec, INSERT_VALUES, SCATTER_REVERSE));
12719566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_N, used_vec, INSERT_VALUES, SCATTER_REVERSE));
12728d00608fSStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
12739566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&dirIS));
12748efcfb23SStefano Zampini     }
1275a07ea27aSStefano Zampini   }
1276b76ba322SStefano Zampini 
12778efcfb23SStefano Zampini   /* remove the computed solution or the initial guess from the rhs */
12788d00608fSStefano Zampini   if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero)) {
127927b6a85dSStefano Zampini     /* save the original rhs */
128027b6a85dSStefano Zampini     if (save_rhs) {
12819566063dSJacob Faibussowitsch       PetscCall(VecSwap(rhs, pcbddc->original_rhs));
128227b6a85dSStefano Zampini       save_rhs = PETSC_FALSE;
12838d00608fSStefano Zampini     }
12848d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
12859566063dSJacob Faibussowitsch     PetscCall(VecScale(used_vec, -1.0));
12869566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(pc->mat, used_vec, pcbddc->original_rhs, rhs));
12879566063dSJacob Faibussowitsch     PetscCall(VecScale(used_vec, -1.0));
12889566063dSJacob Faibussowitsch     PetscCall(VecCopy(used_vec, pcbddc->temp_solution));
128927b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
12901baa6e33SBarry Smith     if (ksp) PetscCall(KSPSetInitialGuessNonzero(ksp, PETSC_FALSE));
12913308cffdSStefano Zampini   }
12929566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&used_vec));
1293b76ba322SStefano Zampini 
1294fc17d649SStefano Zampini   /* compute initial vector in benign space if needed
129527b6a85dSStefano Zampini      and remove non-benign solution from the rhs */
129627b6a85dSStefano Zampini   benign_correction_computed = PETSC_FALSE;
129708af2428SStefano Zampini   if (rhs && pcbddc->benign_compute_correction && (pcbddc->benign_have_null || pcbddc->benign_apply_coarse_only)) {
12981f4df5f7SStefano Zampini     /* compute u^*_h using ideas similar to those in Xuemin Tu's PhD thesis (see Section 4.8.1)
12991f4df5f7SStefano Zampini        Recursively apply BDDC in the multilevel case */
130048a46eb9SPierre Jolivet     if (!pcbddc->benign_vec) PetscCall(VecDuplicate(rhs, &pcbddc->benign_vec));
1301c69e9cc1SStefano Zampini     /* keep applying coarse solver unless we no longer have benign subdomains */
1302c69e9cc1SStefano Zampini     pcbddc->benign_apply_coarse_only = pcbddc->benign_have_null ? PETSC_TRUE : PETSC_FALSE;
130327b6a85dSStefano Zampini     if (!pcbddc->benign_skip_correction) {
13049566063dSJacob Faibussowitsch       PetscCall(PCApply_BDDC(pc, rhs, pcbddc->benign_vec));
13053bca92a6SStefano Zampini       benign_correction_computed = PETSC_TRUE;
13061baa6e33SBarry Smith       if (pcbddc->temp_solution_used) PetscCall(VecAXPY(pcbddc->temp_solution, 1.0, pcbddc->benign_vec));
13079566063dSJacob Faibussowitsch       PetscCall(VecScale(pcbddc->benign_vec, -1.0));
130827b6a85dSStefano Zampini       /* store the original rhs if not done earlier */
13091baa6e33SBarry Smith       if (save_rhs) PetscCall(VecSwap(rhs, pcbddc->original_rhs));
131027b6a85dSStefano Zampini       if (pcbddc->rhs_change) {
13119566063dSJacob Faibussowitsch         PetscCall(MatMultAdd(pc->mat, pcbddc->benign_vec, rhs, rhs));
131227b6a85dSStefano Zampini       } else {
13139566063dSJacob Faibussowitsch         PetscCall(MatMultAdd(pc->mat, pcbddc->benign_vec, pcbddc->original_rhs, rhs));
131427b6a85dSStefano Zampini       }
13150369aaf7SStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
131627b6a85dSStefano Zampini     }
131727b6a85dSStefano Zampini     pcbddc->benign_apply_coarse_only = PETSC_FALSE;
13184df7a6bfSStefano Zampini   } else {
13199566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&pcbddc->benign_vec));
13200369aaf7SStefano Zampini   }
13212d4c4fecSStefano Zampini 
13222d4c4fecSStefano Zampini   /* dbg output */
1323a198735bSStefano Zampini   if (pcbddc->dbg_flag && benign_correction_computed) {
13241f4df5f7SStefano Zampini     Vec v;
1325c69e9cc1SStefano Zampini 
13269566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_global, &v));
1327c69e9cc1SStefano Zampini     if (pcbddc->ChangeOfBasisMatrix) {
13289566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, rhs, v));
1329c69e9cc1SStefano Zampini     } else {
13309566063dSJacob Faibussowitsch       PetscCall(VecCopy(rhs, v));
1331c69e9cc1SStefano Zampini     }
13329566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, v, PETSC_TRUE));
133363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "LEVEL %" PetscInt_FMT ": is the correction benign?\n", pcbddc->current_level));
13349566063dSJacob Faibussowitsch     PetscCall(PetscScalarView(pcbddc->benign_n, pcbddc->benign_p0, pcbddc->dbg_viewer));
13359566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
13369566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&v));
13371f4df5f7SStefano Zampini   }
13380369aaf7SStefano Zampini 
13390369aaf7SStefano Zampini   /* set initial guess if using PCG */
13408ae0ca82SStefano Zampini   pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
13410369aaf7SStefano Zampini   if (x && pcbddc->use_exact_dirichlet_trick) {
13429566063dSJacob Faibussowitsch     PetscCall(VecSet(x, 0.0));
13431dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
134427b6a85dSStefano Zampini       if (benign_correction_computed) { /* we have already saved the changed rhs */
13459566063dSJacob Faibussowitsch         PetscCall(VecLockReadPop(pcis->vec1_global));
13461dd7afcfSStefano Zampini       } else {
13479566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, rhs, pcis->vec1_global));
13481dd7afcfSStefano Zampini       }
13499566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_global, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
13509566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_global, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
13511dd7afcfSStefano Zampini     } else {
13529566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D, rhs, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
13539566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D, rhs, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
13541dd7afcfSStefano Zampini     }
13559566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
13569566063dSJacob Faibussowitsch     PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D));
13579566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
13589566063dSJacob Faibussowitsch     PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D));
13591dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
13609566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_global, 0.));
13619566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, pcis->vec1_global, INSERT_VALUES, SCATTER_REVERSE));
13629566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, pcis->vec1_global, INSERT_VALUES, SCATTER_REVERSE));
13639566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcis->vec1_global, x));
13641dd7afcfSStefano Zampini     } else {
13659566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, x, INSERT_VALUES, SCATTER_REVERSE));
13669566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, x, INSERT_VALUES, SCATTER_REVERSE));
13671dd7afcfSStefano Zampini     }
13681baa6e33SBarry Smith     if (ksp) PetscCall(KSPSetInitialGuessNonzero(ksp, PETSC_TRUE));
13698ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_TRUE;
1370266e20e9SStefano Zampini   } else if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior && benign_correction_computed && pcbddc->use_exact_dirichlet_trick) {
13719566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(pcis->vec1_global));
13720369aaf7SStefano Zampini   }
13733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1374534831adSStefano Zampini }
1375906d46d4SStefano Zampini 
PCPostSolve_BDDC(PC pc,KSP ksp,Vec rhs,Vec x)1376d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1377d71ae5a4SJacob Faibussowitsch {
1378534831adSStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
1379534831adSStefano Zampini 
1380534831adSStefano Zampini   PetscFunctionBegin;
13813972b0daSStefano Zampini   /* add solution removed in presolve */
13826bcfc461SStefano Zampini   if (x && pcbddc->rhs_change) {
138327b6a85dSStefano Zampini     if (pcbddc->temp_solution_used) {
13849566063dSJacob Faibussowitsch       PetscCall(VecAXPY(x, 1.0, pcbddc->temp_solution));
1385af140850Sstefano_zampini     } else if (pcbddc->benign_compute_correction && pcbddc->benign_vec) {
13869566063dSJacob Faibussowitsch       PetscCall(VecAXPY(x, -1.0, pcbddc->benign_vec));
13873425bc38SStefano Zampini     }
1388af140850Sstefano_zampini     /* restore to original state (not for FETI-DP) */
1389af140850Sstefano_zampini     if (ksp) pcbddc->temp_solution_used = PETSC_FALSE;
139027b6a85dSStefano Zampini   }
139127b6a85dSStefano Zampini 
1392266e20e9SStefano Zampini   /* restore rhs to its original state (not needed for FETI-DP) */
13938d00608fSStefano Zampini   if (rhs && pcbddc->rhs_change) {
13949566063dSJacob Faibussowitsch     PetscCall(VecSwap(rhs, pcbddc->original_rhs));
13958d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_FALSE;
1396af140850Sstefano_zampini   }
13978efcfb23SStefano Zampini   /* restore ksp guess state */
13988efcfb23SStefano Zampini   if (ksp) {
13999566063dSJacob Faibussowitsch     PetscCall(KSPSetInitialGuessNonzero(ksp, pcbddc->ksp_guess_nonzero));
14008ae0ca82SStefano Zampini     /* reset flag for exact dirichlet trick */
14018ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
1402af140850Sstefano_zampini   }
14033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1404534831adSStefano Zampini }
1405af140850Sstefano_zampini 
PCSetUp_BDDC(PC pc)140666976f2fSJacob Faibussowitsch static PetscErrorCode PCSetUp_BDDC(PC pc)
1407d71ae5a4SJacob Faibussowitsch {
14080c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC *)pc->data;
1409c703fcc7SStefano Zampini   PCBDDCSubSchurs sub_schurs;
14105e8657edSStefano Zampini   Mat_IS         *matis;
141108122e43SStefano Zampini   MatNullSpace    nearnullspace;
141235509ce9Sstefano_zampini   Mat             lA;
141335509ce9Sstefano_zampini   IS              lP, zerodiag = NULL;
141491e8d312SStefano Zampini   PetscInt        nrows, ncols;
141586bfa4cfSStefano Zampini   PetscMPIInt     size;
1416c703fcc7SStefano Zampini   PetscBool       computesubschurs;
14178de1fae6SStefano Zampini   PetscBool       computeconstraintsmatrix;
14183b03f7bbSStefano Zampini   PetscBool       new_nearnullspace_provided, ismatis, rl;
1419b94d7dedSBarry Smith   PetscBool       isset, issym, isspd;
14200c7d97c5SJed Brown 
14210c7d97c5SJed Brown   PetscFunctionBegin;
14229566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATIS, &ismatis));
142328b400f6SJacob Faibussowitsch   PetscCheck(ismatis, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "PCBDDC preconditioner requires matrix of type MATIS");
14249566063dSJacob Faibussowitsch   PetscCall(MatGetSize(pc->pmat, &nrows, &ncols));
14257addb90fSBarry Smith   PetscCheck(nrows == ncols, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "PCBDDC preconditioner requires a square matrix for constructing the preconditioner");
14269566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
142786bfa4cfSStefano Zampini 
14285e8657edSStefano Zampini   matis = (Mat_IS *)pc->pmat->data;
1429f4ddd8eeSStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */
1430a75bf7bfSStefano Zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetUp
143171582508SStefano Zampini      Also, BDDC builds its own KSP for the Dirichlet problem */
14323b03f7bbSStefano Zampini   rl = pcbddc->recompute_topography;
14333b03f7bbSStefano Zampini   if (!pc->setupcalled || pc->flag == DIFFERENT_NONZERO_PATTERN) rl = PETSC_TRUE;
14345440e5dcSBarry Smith   PetscCallMPI(MPIU_Allreduce(&rl, &pcbddc->recompute_topography, 1, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc)));
1435c83e1ba7SStefano Zampini   if (pcbddc->recompute_topography) {
1436c83e1ba7SStefano Zampini     pcbddc->graphanalyzed    = PETSC_FALSE;
1437c83e1ba7SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1438c83e1ba7SStefano Zampini   } else {
14398de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_FALSE;
1440c83e1ba7SStefano Zampini   }
1441b087196eSStefano Zampini 
1442b087196eSStefano Zampini   /* check parameters' compatibility */
1443b7ab4a40SStefano Zampini   if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE;
1444bd2a564bSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_threshold[0] != 0.0 || pcbddc->adaptive_threshold[1] != 0.0);
1445791bdc09SStefano Zampini   pcbddc->use_deluxe_scaling   = (PetscBool)(pcbddc->use_deluxe_scaling && (size > 1 || matis->allow_repeated));
1446791bdc09SStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_selection && (size > 1 || matis->allow_repeated));
1447bf3a8328SStefano Zampini   pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined);
1448862806e4SStefano Zampini   if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE;
1449862806e4SStefano Zampini 
14505a95e1ceSStefano Zampini   computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling);
145116909a7fSStefano Zampini 
145271582508SStefano Zampini   /* activate all connected components if the netflux has been requested */
1453bb05f991SStefano Zampini   if (pcbddc->compute_nonetflux) {
1454bb05f991SStefano Zampini     pcbddc->use_vertices = PETSC_TRUE;
1455bb05f991SStefano Zampini     pcbddc->use_edges    = PETSC_TRUE;
1456bb05f991SStefano Zampini     pcbddc->use_faces    = PETSC_TRUE;
1457bb05f991SStefano Zampini   }
1458bb05f991SStefano Zampini 
1459f4ddd8eeSStefano Zampini   /* Get stdout for dbg */
146070cf5478SStefano Zampini   if (pcbddc->dbg_flag) {
1461ad540459SPierre Jolivet     if (!pcbddc->dbg_viewer) pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc));
14629566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer));
14639566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIAddTab(pcbddc->dbg_viewer, 2 * pcbddc->current_level));
1464f4ddd8eeSStefano Zampini   }
1465f4ddd8eeSStefano Zampini 
1466c703fcc7SStefano Zampini   /* process topology information */
14679566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Topology[pcbddc->current_level], pc, 0, 0, 0));
146871582508SStefano Zampini   if (pcbddc->recompute_topography) {
14699566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeLocalTopologyInfo(pc));
14701baa6e33SBarry Smith     if (pcbddc->discretegradient) PetscCall(PCBDDCNedelecSupport(pc));
1471c703fcc7SStefano Zampini   }
14724f819b78SStefano Zampini   if (pcbddc->corner_selected) pcbddc->use_vertices = PETSC_TRUE;
1473a13144ffSStefano Zampini 
1474c703fcc7SStefano Zampini   /* change basis if requested by the user */
14755e8657edSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) {
14765e8657edSStefano Zampini     /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */
14775e8657edSStefano Zampini     pcbddc->use_change_of_basis = PETSC_FALSE;
14789566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeLocalMatrix(pc, pcbddc->user_ChangeOfBasisMatrix));
14795e8657edSStefano Zampini   } else {
14809566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcbddc->local_mat));
14819566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)matis->A));
14825e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
1483d16cbb6bSStefano Zampini   }
1484d16cbb6bSStefano Zampini 
14854f1b2e48SStefano Zampini   /*
1486c703fcc7SStefano Zampini      Compute change of basis on local pressures (aka zerodiag dofs) with the benign trick
1487e87b5d96SPierre Jolivet      This should come earlier than PCISSetUp for extracting the correct subdomain matrices
14884f1b2e48SStefano Zampini   */
14899566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignShellMat(pc, PETSC_TRUE));
1490d16cbb6bSStefano Zampini   if (pcbddc->benign_saddle_point) {
14919f47a83aSStefano Zampini     PC_IS *pcis = (PC_IS *)pc->data;
14929f47a83aSStefano Zampini 
149305b28244SStefano Zampini     if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE;
14943b03f7bbSStefano Zampini     /* detect local saddle point and change the basis in pcbddc->local_mat */
14959566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignDetectSaddlePoint(pc, (PetscBool)(!pcbddc->recompute_topography), &zerodiag));
1496a3df083aSStefano Zampini     /* pop B0 mat from local mat */
14979566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignPopOrPushB0(pc, PETSC_TRUE));
14981dd7afcfSStefano Zampini     /* give pcis a hint to not reuse submatrices during PCISCreate */
14991dd7afcfSStefano Zampini     if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) {
15001dd7afcfSStefano Zampini       if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) {
15011dd7afcfSStefano Zampini         pcis->reusesubmatrices = PETSC_FALSE;
15021dd7afcfSStefano Zampini       } else {
1503a3df083aSStefano Zampini         pcis->reusesubmatrices = PETSC_TRUE;
15041dd7afcfSStefano Zampini       }
1505a3df083aSStefano Zampini     } else {
15069f47a83aSStefano Zampini       pcis->reusesubmatrices = PETSC_FALSE;
1507674ae819SStefano Zampini     }
1508a3df083aSStefano Zampini   }
150927b6a85dSStefano Zampini 
15108037d520SStefano Zampini   /* propagate relevant information */
1511b94d7dedSBarry Smith   PetscCall(MatIsSymmetricKnown(matis->A, &isset, &issym));
1512b94d7dedSBarry Smith   if (isset) PetscCall(MatSetOption(pcbddc->local_mat, MAT_SYMMETRIC, issym));
1513b94d7dedSBarry Smith   PetscCall(MatIsSPDKnown(matis->A, &isset, &isspd));
1514b94d7dedSBarry Smith   if (isset) PetscCall(MatSetOption(pcbddc->local_mat, MAT_SPD, isspd));
1515e496cd5dSStefano Zampini 
15165e8657edSStefano Zampini   /* Set up all the "iterative substructuring" common block without computing solvers */
15175e8657edSStefano Zampini   {
15185e8657edSStefano Zampini     Mat temp_mat;
15195e8657edSStefano Zampini 
15205e8657edSStefano Zampini     temp_mat = matis->A;
15215e8657edSStefano Zampini     matis->A = pcbddc->local_mat;
15229566063dSJacob Faibussowitsch     PetscCall(PCISSetUp(pc, PETSC_TRUE, PETSC_FALSE));
15235e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
15245e8657edSStefano Zampini     matis->A          = temp_mat;
15255e8657edSStefano Zampini   }
1526684f6988SStefano Zampini 
152781d14e9dSStefano Zampini   /* Analyze interface */
152864ac59b8SStefano Zampini   if (!pcbddc->graphanalyzed) {
15299566063dSJacob Faibussowitsch     PetscCall(PCBDDCAnalyzeInterface(pc));
15308de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
15310fdf79fbSJacob 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");
1532a198735bSStefano Zampini     if (pcbddc->compute_nonetflux) {
1533669cc0f4SStefano Zampini       MatNullSpace nnfnnsp;
1534669cc0f4SStefano Zampini 
153528b400f6SJacob Faibussowitsch       PetscCheck(pcbddc->divudotp, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Missing divudotp operator");
15369566063dSJacob Faibussowitsch       PetscCall(PCBDDCComputeNoNetFlux(pc->pmat, pcbddc->divudotp, pcbddc->divudotp_trans, pcbddc->divudotp_vl2l, pcbddc->mat_graph, &nnfnnsp));
153771582508SStefano Zampini       /* TODO what if a nearnullspace is already attached? */
15388037d520SStefano Zampini       if (nnfnnsp) {
15399566063dSJacob Faibussowitsch         PetscCall(MatSetNearNullSpace(pc->pmat, nnfnnsp));
15409566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceDestroy(&nnfnnsp));
1541669cc0f4SStefano Zampini       }
1542674ae819SStefano Zampini     }
15438037d520SStefano Zampini   }
15449566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Topology[pcbddc->current_level], pc, 0, 0, 0));
1545fb8d54d4SStefano Zampini 
15465408967cSStefano Zampini   /* check existence of a divergence free extension, i.e.
15475408967cSStefano Zampini      b(v_I,p_0) = 0 for all v_I (raise error if not).
15485408967cSStefano Zampini      Also, check that PCBDDCBenignGetOrSetP0 works */
154948a46eb9SPierre Jolivet   if (pcbddc->benign_saddle_point && pcbddc->dbg_flag > 1) PetscCall(PCBDDCBenignCheck(pc, zerodiag));
15509566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&zerodiag));
155106f24817SStefano Zampini 
1552b96c3477SStefano Zampini   /* Setup local dirichlet solver ksp_D and sub_schurs solvers */
155348a46eb9SPierre Jolivet   if (computesubschurs && pcbddc->recompute_topography) PetscCall(PCBDDCInitSubSchurs(pc));
15549d54b7f4SStefano Zampini   /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/
155548a46eb9SPierre Jolivet   if (!pcbddc->use_deluxe_scaling) PetscCall(PCBDDCScalingSetUp(pc));
1556c703fcc7SStefano Zampini 
1557c703fcc7SStefano Zampini   /* finish setup solvers and do adaptive selection of constraints */
1558b334f244SStefano Zampini   sub_schurs = pcbddc->sub_schurs;
1559b334f244SStefano Zampini   if (sub_schurs && sub_schurs->schur_explicit) {
15601baa6e33SBarry Smith     if (computesubschurs) PetscCall(PCBDDCSetUpSubSchurs(pc));
15619566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetUpLocalSolvers(pc, PETSC_TRUE, PETSC_FALSE));
1562d5574798SStefano Zampini   } else {
15639566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetUpLocalSolvers(pc, PETSC_TRUE, PETSC_FALSE));
15641baa6e33SBarry Smith     if (computesubschurs) PetscCall(PCBDDCSetUpSubSchurs(pc));
15652070dbb6SStefano Zampini   }
156608122e43SStefano Zampini   if (pcbddc->adaptive_selection) {
15679566063dSJacob Faibussowitsch     PetscCall(PCBDDCAdaptiveSelection(pc));
15688de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1569b7eb3628SStefano Zampini   }
1570684f6988SStefano Zampini 
1571f4ddd8eeSStefano Zampini   /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */
1572fb8d54d4SStefano Zampini   new_nearnullspace_provided = PETSC_FALSE;
15739566063dSJacob Faibussowitsch   PetscCall(MatGetNearNullSpace(pc->pmat, &nearnullspace));
1574f4ddd8eeSStefano Zampini   if (pcbddc->onearnullspace) { /* already used nearnullspace */
1575f4ddd8eeSStefano Zampini     if (!nearnullspace) {       /* near null space attached to mat has been destroyed */
1576f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1577f4ddd8eeSStefano Zampini     } else {
1578f4ddd8eeSStefano Zampini       /* determine if the two nullspaces are different (should be lightweight) */
1579f4ddd8eeSStefano Zampini       if (nearnullspace != pcbddc->onearnullspace) {
1580f4ddd8eeSStefano Zampini         new_nearnullspace_provided = PETSC_TRUE;
1581165b64e2SStefano Zampini       } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */
1582f4ddd8eeSStefano Zampini         PetscInt         i;
1583165b64e2SStefano Zampini         const Vec       *nearnullvecs;
1584165b64e2SStefano Zampini         PetscObjectState state;
1585165b64e2SStefano Zampini         PetscInt         nnsp_size;
15869566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceGetVecs(nearnullspace, NULL, &nnsp_size, &nearnullvecs));
1587f4ddd8eeSStefano Zampini         for (i = 0; i < nnsp_size; i++) {
15889566063dSJacob Faibussowitsch           PetscCall(PetscObjectStateGet((PetscObject)nearnullvecs[i], &state));
1589165b64e2SStefano Zampini           if (pcbddc->onearnullvecs_state[i] != state) {
1590f4ddd8eeSStefano Zampini             new_nearnullspace_provided = PETSC_TRUE;
1591f4ddd8eeSStefano Zampini             break;
1592f4ddd8eeSStefano Zampini           }
1593f4ddd8eeSStefano Zampini         }
1594f4ddd8eeSStefano Zampini       }
1595f4ddd8eeSStefano Zampini     }
1596f4ddd8eeSStefano Zampini   } else {
1597f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* both nearnullspaces are null */
1598f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_FALSE;
1599f4ddd8eeSStefano Zampini     } else { /* nearnullspace attached later */
1600f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1601f4ddd8eeSStefano Zampini     }
1602f4ddd8eeSStefano Zampini   }
1603f4ddd8eeSStefano Zampini 
1604f4ddd8eeSStefano Zampini   /* Setup constraints and related work vectors */
1605727cdba6SStefano Zampini   /* reset primal space flags */
16069566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_LocalWork[pcbddc->current_level], pc, 0, 0, 0));
1607f4ddd8eeSStefano Zampini   pcbddc->new_primal_space       = PETSC_FALSE;
1608727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_FALSE;
16098de1fae6SStefano Zampini   if (computeconstraintsmatrix || new_nearnullspace_provided) {
1610727cdba6SStefano Zampini     /* It also sets the primal space flags */
16119566063dSJacob Faibussowitsch     PetscCall(PCBDDCConstraintsSetUp(pc));
16129543d0ffSStefano Zampini   }
1613e7b262bdSStefano Zampini   /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */
16149566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetUpLocalWorkVectors(pc));
16155e8657edSStefano Zampini 
16165e8657edSStefano Zampini   if (pcbddc->use_change_of_basis) {
1617f4f49eeaSPierre Jolivet     PC_IS *pcis = (PC_IS *)pc->data;
16185e8657edSStefano Zampini 
16199566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeLocalMatrix(pc, pcbddc->ChangeOfBasisMatrix));
16204f1b2e48SStefano Zampini     if (pcbddc->benign_change) {
16219566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcbddc->benign_B0));
1622c263805aSStefano Zampini       /* pop B0 from pcbddc->local_mat */
16239566063dSJacob Faibussowitsch       PetscCall(PCBDDCBenignPopOrPushB0(pc, PETSC_TRUE));
1624c263805aSStefano Zampini     }
16255e8657edSStefano Zampini     /* get submatrices */
16269566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_IB));
16279566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_BI));
16289566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_BB));
16299566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_B_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &pcis->A_BB));
16309566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_I_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &pcis->A_IB));
16319566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_B_local, pcis->is_I_local, MAT_INITIAL_MATRIX, &pcis->A_BI));
16323975b054SStefano Zampini     /* set flag in pcis to not reuse submatrices during PCISCreate */
16333975b054SStefano Zampini     pcis->reusesubmatrices = PETSC_FALSE;
16349c6a02ceSStefano Zampini   } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) {
16359566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcbddc->local_mat));
16369566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)matis->A));
16375e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
16385e8657edSStefano Zampini   }
163935509ce9Sstefano_zampini 
164035509ce9Sstefano_zampini   /* interface pressure block row for B_C */
16419566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lP", (PetscObject *)&lP));
16429566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lA", (PetscObject *)&lA));
164335509ce9Sstefano_zampini   if (lA && lP) {
164435509ce9Sstefano_zampini     PC_IS    *pcis = (PC_IS *)pc->data;
164535509ce9Sstefano_zampini     Mat       B_BI, B_BB, Bt_BI, Bt_BB;
164635509ce9Sstefano_zampini     PetscBool issym;
1647b94d7dedSBarry Smith 
16489566063dSJacob Faibussowitsch     PetscCall(MatIsSymmetric(lA, PETSC_SMALL, &issym));
16496cc1294bSstefano_zampini     if (issym) {
16509566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_I_local, MAT_INITIAL_MATRIX, &B_BI));
16519566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_B_local, MAT_INITIAL_MATRIX, &B_BB));
16529566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(B_BI, &Bt_BI));
16539566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(B_BB, &Bt_BB));
165435509ce9Sstefano_zampini     } else {
16559566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_I_local, MAT_INITIAL_MATRIX, &B_BI));
16569566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_B_local, MAT_INITIAL_MATRIX, &B_BB));
16579566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, pcis->is_I_local, lP, MAT_INITIAL_MATRIX, &Bt_BI));
16589566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, pcis->is_B_local, lP, MAT_INITIAL_MATRIX, &Bt_BB));
165935509ce9Sstefano_zampini     }
16609566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_B_BI", (PetscObject)B_BI));
16619566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_B_BB", (PetscObject)B_BB));
16629566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_Bt_BI", (PetscObject)Bt_BI));
16639566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_Bt_BB", (PetscObject)Bt_BB));
16649566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B_BI));
16659566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B_BB));
16669566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Bt_BI));
16679566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Bt_BB));
166835509ce9Sstefano_zampini   }
16699566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_LocalWork[pcbddc->current_level], pc, 0, 0, 0));
167035509ce9Sstefano_zampini 
1671b96c3477SStefano Zampini   /* SetUp coarse and local Neumann solvers */
16729566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetUpSolvers(pc));
1673b96c3477SStefano Zampini   /* SetUp Scaling operator */
16741baa6e33SBarry Smith   if (pcbddc->use_deluxe_scaling) PetscCall(PCBDDCScalingSetUp(pc));
1675c703fcc7SStefano Zampini 
16761dd7afcfSStefano Zampini   /* mark topography as done */
167756282151SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
16780369aaf7SStefano Zampini 
16791dd7afcfSStefano Zampini   /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */
16809566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignShellMat(pc, PETSC_FALSE));
16811dd7afcfSStefano Zampini 
168258a03d70SStefano Zampini   if (pcbddc->dbg_flag) {
16839566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISubtractTab(pcbddc->dbg_viewer, 2 * pcbddc->current_level));
16849566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer));
16852b510759SStefano Zampini   }
16869de2952eSStefano Zampini 
16879de2952eSStefano Zampini   { /* Dump customization */
16889de2952eSStefano Zampini     PetscBool flg;
16899de2952eSStefano Zampini     char      save[PETSC_MAX_PATH_LEN] = {'\0'};
16909de2952eSStefano Zampini 
16919de2952eSStefano Zampini     PetscCall(PetscOptionsGetString(NULL, ((PetscObject)pc)->prefix, "-pc_bddc_save", save, sizeof(save), &flg));
16929de2952eSStefano Zampini     if (flg) {
16939de2952eSStefano Zampini       size_t len;
16949de2952eSStefano Zampini 
16959de2952eSStefano Zampini       PetscCall(PetscStrlen(save, &len));
16969de2952eSStefano Zampini       PetscCall(PCBDDCLoadOrViewCustomization(pc, PETSC_FALSE, len ? save : NULL));
16979de2952eSStefano Zampini     }
16989de2952eSStefano Zampini   }
16993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17000c7d97c5SJed Brown }
17010c7d97c5SJed Brown 
PCApply_BDDC(PC pc,Vec r,Vec z)170266976f2fSJacob Faibussowitsch static PetscErrorCode PCApply_BDDC(PC pc, Vec r, Vec z)
1703d71ae5a4SJacob Faibussowitsch {
1704f4f49eeaSPierre Jolivet   PC_IS            *pcis   = (PC_IS *)pc->data;
1705f4f49eeaSPierre Jolivet   PC_BDDC          *pcbddc = (PC_BDDC *)pc->data;
1706b3338236SStefano Zampini   Mat               lA     = NULL;
1707b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
17083b03a366Sstefano_zampini   const PetscScalar one   = 1.0;
17093b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
17102617d88aSStefano Zampini   const PetscScalar zero  = 0.0;
17110c7d97c5SJed Brown   /* This code is similar to that provided in nn.c for PCNN
17120c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
1713b097fa66SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */
17140c7d97c5SJed Brown 
17150c7d97c5SJed Brown   PetscFunctionBegin;
17169566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(citation, &cited));
171748a46eb9SPierre Jolivet   if (pcbddc->switch_static) PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat, &lA));
1718b3338236SStefano Zampini 
17191dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
17201dd7afcfSStefano Zampini     Vec swap;
172127b6a85dSStefano Zampini 
17229566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, r, pcbddc->work_change));
17231dd7afcfSStefano Zampini     swap                = pcbddc->work_change;
17241dd7afcfSStefano Zampini     pcbddc->work_change = r;
17251dd7afcfSStefano Zampini     r                   = swap;
17261dd7afcfSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
17279cc2a9b1Sstefano_zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) {
17289566063dSJacob Faibussowitsch       PetscCall(VecCopy(r, pcis->vec1_global));
17299566063dSJacob Faibussowitsch       PetscCall(VecLockReadPush(pcis->vec1_global));
17301dd7afcfSStefano Zampini     }
17311dd7afcfSStefano Zampini   }
173227b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
17339566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, r, PETSC_TRUE));
1734efc2fbd9SStefano Zampini   }
1735bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET && !pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
17369566063dSJacob Faibussowitsch     PetscCall(VecCopy(r, z));
17370c7d97c5SJed Brown     /* First Dirichlet solve */
17389566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
17399566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
17400c7d97c5SJed Brown     /*
1741dd8e379bSPierre Jolivet       Assembling right-hand side for BDDC operator
1742b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
1743674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
17440c7d97c5SJed Brown     */
17459566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
1746a1cb837bSStefano Zampini     if (n_D) {
17479566063dSJacob Faibussowitsch       PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D));
17489566063dSJacob Faibussowitsch       PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
17499566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D));
17509566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec2_D, m_one));
175116909a7fSStefano Zampini       if (pcbddc->switch_static) {
17529566063dSJacob Faibussowitsch         PetscCall(VecSet(pcis->vec1_N, 0.));
17539566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
17549566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
175516909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
17569566063dSJacob Faibussowitsch           PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N));
175716909a7fSStefano Zampini         } else {
17589566063dSJacob Faibussowitsch           PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
17599566063dSJacob Faibussowitsch           PetscCall(MatMult(lA, pcis->vec2_N, pcis->vec1_N));
17609566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
176116909a7fSStefano Zampini         }
17629566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD));
17639566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD));
17649566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
17659566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
176616909a7fSStefano Zampini       } else {
17679566063dSJacob Faibussowitsch         PetscCall(MatMult(pcis->A_BI, pcis->vec2_D, pcis->vec1_B));
176816909a7fSStefano Zampini       }
1769b097fa66SStefano Zampini     } else {
1770a1cb837bSStefano Zampini       PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
17719566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_B, zero));
1772b097fa66SStefano Zampini     }
17739566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE));
17749566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE));
17759566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingRestriction(pc, z, pcis->vec1_B));
1776b76ba322SStefano Zampini   } else {
177748a46eb9SPierre Jolivet     if (!pcbddc->benign_apply_coarse_only) PetscCall(PCBDDCScalingRestriction(pc, r, pcis->vec1_B));
17784fee134fSStefano Zampini   }
1779bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) {
178028b400f6SJacob Faibussowitsch     PetscCheck(pcbddc->switch_static, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "You forgot to pass -pc_bddc_switch_static");
17819566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
17829566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
1783bc960bbfSJed Brown   }
1784b76ba322SStefano Zampini 
17852617d88aSStefano Zampini   /* Apply interface preconditioner
17862617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
17879566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(pc, PETSC_FALSE));
17882617d88aSStefano Zampini 
1789674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
17909566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(pc, pcis->vec1_B, z));
1791bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) {
17929566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_D, z, INSERT_VALUES, SCATTER_REVERSE));
17939566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_D, z, INSERT_VALUES, SCATTER_REVERSE));
17943ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1795bc960bbfSJed Brown   }
17963b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
17979566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
17989566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
1799b097fa66SStefano Zampini   if (n_B) {
180016909a7fSStefano Zampini     if (pcbddc->switch_static) {
18019566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
18029566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
18039566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
18049566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
180516909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
18069566063dSJacob Faibussowitsch         PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N));
180716909a7fSStefano Zampini       } else {
18089566063dSJacob Faibussowitsch         PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
18099566063dSJacob Faibussowitsch         PetscCall(MatMult(lA, pcis->vec2_N, pcis->vec1_N));
18109566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
181116909a7fSStefano Zampini       }
18129566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD));
18139566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD));
181416909a7fSStefano Zampini     } else {
18159566063dSJacob Faibussowitsch       PetscCall(MatMult(pcis->A_IB, pcis->vec1_B, pcis->vec3_D));
181616909a7fSStefano Zampini     }
181716909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
181816909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
18199566063dSJacob Faibussowitsch       PetscCall(MatMult(lA, pcis->vec1_D, pcis->vec3_D));
182016909a7fSStefano Zampini     } else {
18219566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_D, pcis->vec1_N));
18229566063dSJacob Faibussowitsch       PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N));
18239566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec2_N, pcis->vec3_D));
182416909a7fSStefano Zampini     }
1825b097fa66SStefano Zampini   }
18269566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
18279566063dSJacob Faibussowitsch   PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec3_D, pcis->vec4_D));
18289566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
18299566063dSJacob Faibussowitsch   PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec4_D));
1830efc2fbd9SStefano Zampini 
18318ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1832b097fa66SStefano Zampini     if (pcbddc->switch_static) {
18339566063dSJacob Faibussowitsch       PetscCall(VecAXPBYPCZ(pcis->vec2_D, m_one, one, m_one, pcis->vec4_D, pcis->vec1_D));
1834b097fa66SStefano Zampini     } else {
18359566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec2_D, m_one, m_one, pcis->vec4_D));
1836b097fa66SStefano Zampini     }
18379566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE));
18389566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE));
1839b097fa66SStefano Zampini   } else {
1840b097fa66SStefano Zampini     if (pcbddc->switch_static) {
18419566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec4_D, one, m_one, pcis->vec1_D));
1842b097fa66SStefano Zampini     } else {
18439566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec4_D, m_one));
1844b097fa66SStefano Zampini     }
18459566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE));
18469566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE));
1847b097fa66SStefano Zampini   }
184827b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
18491baa6e33SBarry Smith     if (pcbddc->benign_apply_coarse_only) PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n));
18509566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, z, PETSC_FALSE));
1851efc2fbd9SStefano Zampini   }
18521f4df5f7SStefano Zampini 
18531dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1854f913dca9SStefano Zampini     pcbddc->work_change = r;
18559566063dSJacob Faibussowitsch     PetscCall(VecCopy(z, pcbddc->work_change));
18569566063dSJacob Faibussowitsch     PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcbddc->work_change, z));
18571dd7afcfSStefano Zampini   }
18583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18590c7d97c5SJed Brown }
186050efa1b5SStefano Zampini 
PCApplyTranspose_BDDC(PC pc,Vec r,Vec z)186166976f2fSJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_BDDC(PC pc, Vec r, Vec z)
1862d71ae5a4SJacob Faibussowitsch {
1863f4f49eeaSPierre Jolivet   PC_IS            *pcis   = (PC_IS *)pc->data;
1864f4f49eeaSPierre Jolivet   PC_BDDC          *pcbddc = (PC_BDDC *)pc->data;
1865b3338236SStefano Zampini   Mat               lA     = NULL;
1866b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
186750efa1b5SStefano Zampini   const PetscScalar one   = 1.0;
186850efa1b5SStefano Zampini   const PetscScalar m_one = -1.0;
186950efa1b5SStefano Zampini   const PetscScalar zero  = 0.0;
187050efa1b5SStefano Zampini 
187150efa1b5SStefano Zampini   PetscFunctionBegin;
18729566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(citation, &cited));
187348a46eb9SPierre Jolivet   if (pcbddc->switch_static) PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat, &lA));
18741dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
18751dd7afcfSStefano Zampini     Vec swap;
187627b6a85dSStefano Zampini 
18779566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, r, pcbddc->work_change));
18781dd7afcfSStefano Zampini     swap                = pcbddc->work_change;
18791dd7afcfSStefano Zampini     pcbddc->work_change = r;
18801dd7afcfSStefano Zampini     r                   = swap;
188127b6a85dSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
18828ae0ca82SStefano Zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->exact_dirichlet_trick_app && pcbddc->change_interior) {
18839566063dSJacob Faibussowitsch       PetscCall(VecCopy(r, pcis->vec1_global));
18849566063dSJacob Faibussowitsch       PetscCall(VecLockReadPush(pcis->vec1_global));
18851dd7afcfSStefano Zampini     }
188627b6a85dSStefano Zampini   }
188727b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
18889566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, r, PETSC_TRUE));
1889537c1cdfSStefano Zampini   }
18908ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
18919566063dSJacob Faibussowitsch     PetscCall(VecCopy(r, z));
189250efa1b5SStefano Zampini     /* First Dirichlet solve */
18939566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
18949566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
189550efa1b5SStefano Zampini     /*
1896dd8e379bSPierre Jolivet       Assembling right-hand side for BDDC operator
1897b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
189850efa1b5SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
189950efa1b5SStefano Zampini     */
1900b097fa66SStefano Zampini     if (n_D) {
19019566063dSJacob Faibussowitsch       PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
19029566063dSJacob Faibussowitsch       PetscCall(KSPSolveTranspose(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D));
19039566063dSJacob Faibussowitsch       PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
19049566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D));
19059566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec2_D, m_one));
190616909a7fSStefano Zampini       if (pcbddc->switch_static) {
19079566063dSJacob Faibussowitsch         PetscCall(VecSet(pcis->vec1_N, 0.));
19089566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
19099566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
191016909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
19119566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N));
191216909a7fSStefano Zampini         } else {
19139566063dSJacob Faibussowitsch           PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
19149566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(lA, pcis->vec2_N, pcis->vec1_N));
19159566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
191616909a7fSStefano Zampini         }
19179566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD));
19189566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD));
19199566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
19209566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
192116909a7fSStefano Zampini       } else {
19229566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcis->A_IB, pcis->vec2_D, pcis->vec1_B));
192316909a7fSStefano Zampini       }
1924b097fa66SStefano Zampini     } else {
19259566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_B, zero));
1926b097fa66SStefano Zampini     }
19279566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE));
19289566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE));
19299566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingRestriction(pc, z, pcis->vec1_B));
193050efa1b5SStefano Zampini   } else {
19319566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingRestriction(pc, r, pcis->vec1_B));
193250efa1b5SStefano Zampini   }
193350efa1b5SStefano Zampini 
193450efa1b5SStefano Zampini   /* Apply interface preconditioner
193550efa1b5SStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
19369566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(pc, PETSC_TRUE));
193750efa1b5SStefano Zampini 
193850efa1b5SStefano Zampini   /* Apply transpose of partition of unity operator */
19399566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(pc, pcis->vec1_B, z));
194050efa1b5SStefano Zampini 
194150efa1b5SStefano Zampini   /* Second Dirichlet solve and assembling of output */
19429566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
19439566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
1944b097fa66SStefano Zampini   if (n_B) {
194516909a7fSStefano Zampini     if (pcbddc->switch_static) {
19469566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
19479566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
19489566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
19499566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
195016909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
19519566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N));
195216909a7fSStefano Zampini       } else {
19539566063dSJacob Faibussowitsch         PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
19549566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(lA, pcis->vec2_N, pcis->vec1_N));
19559566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
195616909a7fSStefano Zampini       }
19579566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD));
19589566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD));
195916909a7fSStefano Zampini     } else {
19609566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcis->A_BI, pcis->vec1_B, pcis->vec3_D));
196116909a7fSStefano Zampini     }
196216909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
196316909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
19649566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(lA, pcis->vec1_D, pcis->vec3_D));
196516909a7fSStefano Zampini     } else {
19669566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_D, pcis->vec1_N));
19679566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N));
19689566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec2_N, pcis->vec3_D));
196916909a7fSStefano Zampini     }
1970b097fa66SStefano Zampini   }
19719566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
19729566063dSJacob Faibussowitsch   PetscCall(KSPSolveTranspose(pcbddc->ksp_D, pcis->vec3_D, pcis->vec4_D));
19739566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
19749566063dSJacob Faibussowitsch   PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec4_D));
19758ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1976b097fa66SStefano Zampini     if (pcbddc->switch_static) {
19779566063dSJacob Faibussowitsch       PetscCall(VecAXPBYPCZ(pcis->vec2_D, m_one, one, m_one, pcis->vec4_D, pcis->vec1_D));
1978b097fa66SStefano Zampini     } else {
19799566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec2_D, m_one, m_one, pcis->vec4_D));
1980b097fa66SStefano Zampini     }
19819566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE));
19829566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE));
1983b097fa66SStefano Zampini   } else {
1984b097fa66SStefano Zampini     if (pcbddc->switch_static) {
19859566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec4_D, one, m_one, pcis->vec1_D));
1986b097fa66SStefano Zampini     } else {
19879566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec4_D, m_one));
1988b097fa66SStefano Zampini     }
19899566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE));
19909566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE));
1991b097fa66SStefano Zampini   }
199227b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
19939566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, z, PETSC_FALSE));
1994537c1cdfSStefano Zampini   }
19951dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1996f913dca9SStefano Zampini     pcbddc->work_change = r;
19979566063dSJacob Faibussowitsch     PetscCall(VecCopy(z, pcbddc->work_change));
19989566063dSJacob Faibussowitsch     PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcbddc->work_change, z));
19991dd7afcfSStefano Zampini   }
20003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
200150efa1b5SStefano Zampini }
2002674ae819SStefano Zampini 
PCReset_BDDC(PC pc)200366976f2fSJacob Faibussowitsch static PetscErrorCode PCReset_BDDC(PC pc)
2004d71ae5a4SJacob Faibussowitsch {
2005da1bb401SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
20069326c5c6Sstefano_zampini   PC_IS   *pcis   = (PC_IS *)pc->data;
20079326c5c6Sstefano_zampini   KSP      kspD, kspR, kspC;
2008da1bb401SStefano Zampini 
2009da1bb401SStefano Zampini   PetscFunctionBegin;
2010674ae819SStefano Zampini   /* free BDDC custom data  */
20119566063dSJacob Faibussowitsch   PetscCall(PCBDDCResetCustomization(pc));
2012674ae819SStefano Zampini   /* destroy objects related to topography */
20139566063dSJacob Faibussowitsch   PetscCall(PCBDDCResetTopography(pc));
201434a97f8cSStefano Zampini   /* destroy objects for scaling operator */
20159566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingDestroy(pc));
2016674ae819SStefano Zampini   /* free solvers stuff */
20179566063dSJacob Faibussowitsch   PetscCall(PCBDDCResetSolvers(pc));
201862a6ff1dSStefano Zampini   /* free global vectors needed in presolve */
20199566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->temp_solution));
20209566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->original_rhs));
20211dd7afcfSStefano Zampini   /* free data created by PCIS */
202204c3f3b8SBarry Smith   PetscCall(PCISReset(pc));
20239326c5c6Sstefano_zampini 
20249326c5c6Sstefano_zampini   /* restore defaults */
20259326c5c6Sstefano_zampini   kspD = pcbddc->ksp_D;
20269326c5c6Sstefano_zampini   kspR = pcbddc->ksp_R;
20279326c5c6Sstefano_zampini   kspC = pcbddc->coarse_ksp;
20289566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(pc->data, sizeof(*pcbddc)));
20299326c5c6Sstefano_zampini   pcis->n_neigh                     = -1;
20309326c5c6Sstefano_zampini   pcis->scaling_factor              = 1.0;
20319326c5c6Sstefano_zampini   pcis->reusesubmatrices            = PETSC_TRUE;
20329326c5c6Sstefano_zampini   pcbddc->use_local_adj             = PETSC_TRUE;
20339326c5c6Sstefano_zampini   pcbddc->use_vertices              = PETSC_TRUE;
20349326c5c6Sstefano_zampini   pcbddc->use_edges                 = PETSC_TRUE;
20359326c5c6Sstefano_zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
20369326c5c6Sstefano_zampini   pcbddc->vertex_size               = 1;
20379326c5c6Sstefano_zampini   pcbddc->recompute_topography      = PETSC_TRUE;
20389326c5c6Sstefano_zampini   pcbddc->coarse_size               = -1;
20399326c5c6Sstefano_zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
20409326c5c6Sstefano_zampini   pcbddc->coarsening_ratio          = 8;
20419326c5c6Sstefano_zampini   pcbddc->coarse_eqs_per_proc       = 1;
20429326c5c6Sstefano_zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
20439326c5c6Sstefano_zampini   pcbddc->nedfield                  = -1;
20449326c5c6Sstefano_zampini   pcbddc->nedglobal                 = PETSC_TRUE;
20451690c2aeSBarry Smith   pcbddc->graphmaxcount             = PETSC_INT_MAX;
20469326c5c6Sstefano_zampini   pcbddc->sub_schurs_layers         = -1;
20479326c5c6Sstefano_zampini   pcbddc->ksp_D                     = kspD;
20489326c5c6Sstefano_zampini   pcbddc->ksp_R                     = kspR;
20499326c5c6Sstefano_zampini   pcbddc->coarse_ksp                = kspC;
20503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20519326c5c6Sstefano_zampini }
20529326c5c6Sstefano_zampini 
PCDestroy_BDDC(PC pc)205366976f2fSJacob Faibussowitsch static PetscErrorCode PCDestroy_BDDC(PC pc)
2054d71ae5a4SJacob Faibussowitsch {
20559326c5c6Sstefano_zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
20569326c5c6Sstefano_zampini 
20579326c5c6Sstefano_zampini   PetscFunctionBegin;
20589566063dSJacob Faibussowitsch   PetscCall(PCReset_BDDC(pc));
20599566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcbddc->ksp_D));
20609566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcbddc->ksp_R));
20619566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcbddc->coarse_ksp));
20629566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDiscreteGradient_C", NULL));
20639566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDivergenceMat_C", NULL));
20649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetChangeOfBasisMat_C", NULL));
20659566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesLocalIS_C", NULL));
20669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesIS_C", NULL));
206732fe681dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesLocalIS_C", NULL));
206832fe681dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesIS_C", NULL));
20699566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetCoarseningRatio_C", NULL));
20709566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevel_C", NULL));
20719566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetUseExactDirichlet_C", NULL));
20729566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevels_C", NULL));
20739566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundaries_C", NULL));
20749566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundariesLocal_C", NULL));
20759566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundaries_C", NULL));
20769566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundariesLocal_C", NULL));
20779566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundaries_C", NULL));
20789566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundariesLocal_C", NULL));
20799566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundaries_C", NULL));
20809566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundariesLocal_C", NULL));
20819566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplitting_C", NULL));
20829566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplittingLocal_C", NULL));
20839566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", NULL));
20849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCCreateFETIDPOperators_C", NULL));
20859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetRHS_C", NULL));
20869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetSolution_C", NULL));
20879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", NULL));
20889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", NULL));
20899566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
20903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2091da1bb401SStefano Zampini }
20921e6b0712SBarry Smith 
PCSetCoordinates_BDDC(PC pc,PetscInt dim,PetscInt nloc,PetscReal * coords)2093d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetCoordinates_BDDC(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
2094d71ae5a4SJacob Faibussowitsch {
2095ab8c8b98SStefano Zampini   PC_BDDC    *pcbddc    = (PC_BDDC *)pc->data;
2096ab8c8b98SStefano Zampini   PCBDDCGraph mat_graph = pcbddc->mat_graph;
2097ab8c8b98SStefano Zampini 
2098ab8c8b98SStefano Zampini   PetscFunctionBegin;
20999566063dSJacob Faibussowitsch   PetscCall(PetscFree(mat_graph->coords));
21009566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nloc * dim, &mat_graph->coords));
21019566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(mat_graph->coords, coords, nloc * dim));
2102ab8c8b98SStefano Zampini   mat_graph->cnloc = nloc;
2103ab8c8b98SStefano Zampini   mat_graph->cdim  = dim;
2104ab8c8b98SStefano Zampini   mat_graph->cloc  = PETSC_FALSE;
21054f819b78SStefano Zampini   /* flg setup */
21064f819b78SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
21074f819b78SStefano Zampini   pcbddc->corner_selected      = PETSC_FALSE;
21083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2109ab8c8b98SStefano Zampini }
2110ab8c8b98SStefano Zampini 
PCPreSolveChangeRHS_BDDC(PC pc,PetscBool * change)2111d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCPreSolveChangeRHS_BDDC(PC pc, PetscBool *change)
2112d71ae5a4SJacob Faibussowitsch {
2113a06fd7f2SStefano Zampini   PetscFunctionBegin;
2114a06fd7f2SStefano Zampini   *change = PETSC_TRUE;
21153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2116a06fd7f2SStefano Zampini }
2117a06fd7f2SStefano Zampini 
PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat,Vec standard_rhs,Vec fetidp_flux_rhs)2118d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
2119d71ae5a4SJacob Faibussowitsch {
2120674ae819SStefano Zampini   FETIDPMat_ctx mat_ctx;
2121266e20e9SStefano Zampini   Vec           work;
21223425bc38SStefano Zampini   PC_IS        *pcis;
21233425bc38SStefano Zampini   PC_BDDC      *pcbddc;
21240c7d97c5SJed Brown 
21253425bc38SStefano Zampini   PetscFunctionBegin;
21269566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx));
21273425bc38SStefano Zampini   pcis   = (PC_IS *)mat_ctx->pc->data;
21283425bc38SStefano Zampini   pcbddc = (PC_BDDC *)mat_ctx->pc->data;
21293425bc38SStefano Zampini 
21309566063dSJacob Faibussowitsch   PetscCall(VecSet(fetidp_flux_rhs, 0.0));
2131229984c5Sstefano_zampini   /* copy rhs since we may change it during PCPreSolve_BDDC */
213248a46eb9SPierre Jolivet   if (!pcbddc->original_rhs) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->original_rhs));
21336cc1294bSstefano_zampini   if (mat_ctx->rhs_flip) {
21349566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(pcbddc->original_rhs, standard_rhs, mat_ctx->rhs_flip));
21356cc1294bSstefano_zampini   } else {
21369566063dSJacob Faibussowitsch     PetscCall(VecCopy(standard_rhs, pcbddc->original_rhs));
21376cc1294bSstefano_zampini   }
2138af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
2139229984c5Sstefano_zampini     /* interface pressure rhs */
21409566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->g2g_p, fetidp_flux_rhs, pcbddc->original_rhs, INSERT_VALUES, SCATTER_REVERSE));
21419566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->g2g_p, fetidp_flux_rhs, pcbddc->original_rhs, INSERT_VALUES, SCATTER_REVERSE));
21429566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->g2g_p, standard_rhs, fetidp_flux_rhs, INSERT_VALUES, SCATTER_FORWARD));
21439566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->g2g_p, standard_rhs, fetidp_flux_rhs, INSERT_VALUES, SCATTER_FORWARD));
214448a46eb9SPierre Jolivet     if (!mat_ctx->rhs_flip) PetscCall(VecScale(fetidp_flux_rhs, -1.));
21456cc1294bSstefano_zampini   }
2146c08af4c6SStefano Zampini   /*
2147c08af4c6SStefano Zampini      change of basis for physical rhs if needed
2148c08af4c6SStefano Zampini      It also changes the rhs in case of dirichlet boundaries
2149c08af4c6SStefano Zampini   */
21509566063dSJacob Faibussowitsch   PetscCall(PCPreSolve_BDDC(mat_ctx->pc, NULL, pcbddc->original_rhs, NULL));
2151fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
21529566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, pcbddc->original_rhs, pcbddc->work_change));
21533738a8e6SStefano Zampini     work = pcbddc->work_change;
2154fc17d649SStefano Zampini   } else {
21553738a8e6SStefano Zampini     work = pcbddc->original_rhs;
2156fc17d649SStefano Zampini   }
21573425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
21589566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_D, work, mat_ctx->temp_solution_D, INSERT_VALUES, SCATTER_FORWARD));
21599566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_D, work, mat_ctx->temp_solution_D, INSERT_VALUES, SCATTER_FORWARD));
2160fb223d50SStefano Zampini   /* scale rhs since it should be unassembled */
2161fb223d50SStefano Zampini   /* TODO use counter scaling? (also below) */
21629566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD));
21639566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD));
2164674ae819SStefano Zampini   /* Apply partition of unity */
21659566063dSJacob Faibussowitsch   PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B, pcis->D, mat_ctx->temp_solution_B));
21669566063dSJacob Faibussowitsch   /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */
21678eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
21683425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
21699566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0));
21709566063dSJacob Faibussowitsch     PetscCall(KSPSolve(pcbddc->ksp_D, mat_ctx->temp_solution_D, pcis->vec1_D));
21719566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0));
2172c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
21739566063dSJacob Faibussowitsch     PetscCall(MatMult(pcis->A_BI, pcis->vec1_D, pcis->vec1_B));
21749566063dSJacob Faibussowitsch     PetscCall(VecAXPY(mat_ctx->temp_solution_B, -1.0, pcis->vec1_B));
21759566063dSJacob Faibussowitsch     PetscCall(VecSet(work, 0.0));
21769566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, mat_ctx->temp_solution_B, work, ADD_VALUES, SCATTER_REVERSE));
21779566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, mat_ctx->temp_solution_B, work, ADD_VALUES, SCATTER_REVERSE));
21789566063dSJacob Faibussowitsch     /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */
21799566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD));
21809566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD));
21819566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B, pcis->D, mat_ctx->temp_solution_B));
21823425bc38SStefano Zampini   }
21833425bc38SStefano Zampini   /* BDDC rhs */
21849566063dSJacob Faibussowitsch   PetscCall(VecCopy(mat_ctx->temp_solution_B, pcis->vec1_B));
21851baa6e33SBarry Smith   if (pcbddc->switch_static) PetscCall(VecCopy(mat_ctx->temp_solution_D, pcis->vec1_D));
21863425bc38SStefano Zampini   /* apply BDDC */
21879566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n));
21889566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc, PETSC_FALSE));
21899566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n));
2190229984c5Sstefano_zampini 
21913425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
21929566063dSJacob Faibussowitsch   PetscCall(MatMult(mat_ctx->B_delta, pcis->vec1_B, mat_ctx->lambda_local));
21939566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(mat_ctx->l2g_lambda, mat_ctx->lambda_local, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD));
21949566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(mat_ctx->l2g_lambda, mat_ctx->lambda_local, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD));
2195229984c5Sstefano_zampini   /* Add contribution to interface pressures */
2196229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
219726699680SStefano Zampini     PetscCall(VecISSet(pcis->vec1_B, mat_ctx->lP_B, 0));
21989566063dSJacob Faibussowitsch     PetscCall(MatMult(mat_ctx->B_BB, pcis->vec1_B, mat_ctx->vP));
219926699680SStefano Zampini     if (pcbddc->switch_static) {
220026699680SStefano Zampini       PetscCall(VecISSet(pcis->vec1_D, mat_ctx->lP_I, 0));
220126699680SStefano Zampini       PetscCall(MatMultAdd(mat_ctx->B_BI, pcis->vec1_D, mat_ctx->vP, mat_ctx->vP));
220226699680SStefano Zampini     }
22039566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->l2g_p, mat_ctx->vP, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD));
22049566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->l2g_p, mat_ctx->vP, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD));
2205229984c5Sstefano_zampini   }
22063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22073425bc38SStefano Zampini }
22081e6b0712SBarry Smith 
22093425bc38SStefano Zampini /*@
221098ad52f2SBarry Smith   PCBDDCMatFETIDPGetRHS - Compute the right-hand side for a FETI-DP linear system using the physical right-hand side
22113425bc38SStefano Zampini 
22123425bc38SStefano Zampini   Collective
22133425bc38SStefano Zampini 
22143425bc38SStefano Zampini   Input Parameters:
2215f1580f4eSBarry Smith + fetidp_mat   - the FETI-DP matrix object obtained by a call to `PCBDDCCreateFETIDPOperators()`
22160f202f7eSStefano Zampini - standard_rhs - the right-hand side of the original linear system
22173425bc38SStefano Zampini 
2218f1580f4eSBarry Smith   Output Parameter:
22190f202f7eSStefano Zampini . fetidp_flux_rhs - the right-hand side for the FETI-DP linear system
22203425bc38SStefano Zampini 
22213425bc38SStefano Zampini   Level: developer
22223425bc38SStefano Zampini 
2223f6cc42faSStefano Zampini   Note:
2224f6cc42faSStefano Zampini   Most users should employ the `KSP` interface for linear solvers and create a solver of type `KSPFETIDP`.
2225f6cc42faSStefano Zampini 
2226562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCCreateFETIDPOperators()`, `PCBDDCMatFETIDPGetSolution()`
22273425bc38SStefano Zampini @*/
PCBDDCMatFETIDPGetRHS(Mat fetidp_mat,Vec standard_rhs,Vec fetidp_flux_rhs)2228d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
2229d71ae5a4SJacob Faibussowitsch {
2230674ae819SStefano Zampini   FETIDPMat_ctx mat_ctx;
22313425bc38SStefano Zampini 
22323425bc38SStefano Zampini   PetscFunctionBegin;
2233266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat, MAT_CLASSID, 1);
2234266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_rhs, VEC_CLASSID, 2);
2235266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_rhs, VEC_CLASSID, 3);
22369566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx));
2237cac4c232SBarry Smith   PetscUseMethod(mat_ctx->pc, "PCBDDCMatFETIDPGetRHS_C", (Mat, Vec, Vec), (fetidp_mat, standard_rhs, fetidp_flux_rhs));
22383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22393425bc38SStefano Zampini }
22401e6b0712SBarry Smith 
PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat,Vec fetidp_flux_sol,Vec standard_sol)2241d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
2242d71ae5a4SJacob Faibussowitsch {
2243674ae819SStefano Zampini   FETIDPMat_ctx mat_ctx;
22443425bc38SStefano Zampini   PC_IS        *pcis;
22453425bc38SStefano Zampini   PC_BDDC      *pcbddc;
2246229984c5Sstefano_zampini   Vec           work;
22473425bc38SStefano Zampini 
22483425bc38SStefano Zampini   PetscFunctionBegin;
22499566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx));
22503425bc38SStefano Zampini   pcis   = (PC_IS *)mat_ctx->pc->data;
22513425bc38SStefano Zampini   pcbddc = (PC_BDDC *)mat_ctx->pc->data;
22523425bc38SStefano Zampini 
22533425bc38SStefano Zampini   /* apply B_delta^T */
22549566063dSJacob Faibussowitsch   PetscCall(VecSet(pcis->vec1_B, 0.));
22559566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(mat_ctx->l2g_lambda, fetidp_flux_sol, mat_ctx->lambda_local, INSERT_VALUES, SCATTER_REVERSE));
22569566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(mat_ctx->l2g_lambda, fetidp_flux_sol, mat_ctx->lambda_local, INSERT_VALUES, SCATTER_REVERSE));
22579566063dSJacob Faibussowitsch   PetscCall(MatMultTranspose(mat_ctx->B_delta, mat_ctx->lambda_local, pcis->vec1_B));
2258229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
22599566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->l2g_p, fetidp_flux_sol, mat_ctx->vP, INSERT_VALUES, SCATTER_REVERSE));
22609566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->l2g_p, fetidp_flux_sol, mat_ctx->vP, INSERT_VALUES, SCATTER_REVERSE));
22619566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(mat_ctx->Bt_BB, mat_ctx->vP, pcis->vec1_B, pcis->vec1_B));
2262229984c5Sstefano_zampini   }
2263229984c5Sstefano_zampini 
22643425bc38SStefano Zampini   /* compute rhs for BDDC application */
22659566063dSJacob Faibussowitsch   PetscCall(VecAYPX(pcis->vec1_B, -1.0, mat_ctx->temp_solution_B));
22668eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
22679566063dSJacob Faibussowitsch     PetscCall(VecCopy(mat_ctx->temp_solution_D, pcis->vec1_D));
2268229984c5Sstefano_zampini     if (mat_ctx->l2g_p) {
22699566063dSJacob Faibussowitsch       PetscCall(VecScale(mat_ctx->vP, -1.));
22709566063dSJacob Faibussowitsch       PetscCall(MatMultAdd(mat_ctx->Bt_BI, mat_ctx->vP, pcis->vec1_D, pcis->vec1_D));
22713425bc38SStefano Zampini     }
2272229984c5Sstefano_zampini   }
2273229984c5Sstefano_zampini 
22743425bc38SStefano Zampini   /* apply BDDC */
22759566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n));
22769566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc, PETSC_FALSE));
2277229984c5Sstefano_zampini 
2278229984c5Sstefano_zampini   /* put values into global vector */
2279af140850Sstefano_zampini   if (pcbddc->ChangeOfBasisMatrix) work = pcbddc->work_change;
2280af140850Sstefano_zampini   else work = standard_sol;
22819566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, work, INSERT_VALUES, SCATTER_REVERSE));
22829566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, work, INSERT_VALUES, SCATTER_REVERSE));
22838eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
22843425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
22859566063dSJacob Faibussowitsch     PetscCall(MatMult(pcis->A_IB, pcis->vec1_B, pcis->vec1_D));
22869566063dSJacob Faibussowitsch     PetscCall(VecAYPX(pcis->vec1_D, -1.0, mat_ctx->temp_solution_D));
22879566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0));
22889566063dSJacob Faibussowitsch     PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec1_D));
22899566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0));
2290c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
22913425bc38SStefano Zampini   }
2292229984c5Sstefano_zampini 
22939566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_D, work, INSERT_VALUES, SCATTER_REVERSE));
22949566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_D, work, INSERT_VALUES, SCATTER_REVERSE));
2295266e20e9SStefano Zampini   /* add p0 solution to final solution */
22969566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignGetOrSetP0(mat_ctx->pc, work, PETSC_FALSE));
22971baa6e33SBarry Smith   if (pcbddc->ChangeOfBasisMatrix) PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, work, standard_sol));
22989566063dSJacob Faibussowitsch   PetscCall(PCPostSolve_BDDC(mat_ctx->pc, NULL, NULL, standard_sol));
2299af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
23009566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->g2g_p, fetidp_flux_sol, standard_sol, INSERT_VALUES, SCATTER_REVERSE));
23019566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->g2g_p, fetidp_flux_sol, standard_sol, INSERT_VALUES, SCATTER_REVERSE));
2302229984c5Sstefano_zampini   }
23033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23043425bc38SStefano Zampini }
23051e6b0712SBarry Smith 
PCView_BDDCIPC(PC pc,PetscViewer viewer)2306d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_BDDCIPC(PC pc, PetscViewer viewer)
2307d71ae5a4SJacob Faibussowitsch {
23085a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
23095a1e936bSStefano Zampini   PetscBool   isascii;
23105a1e936bSStefano Zampini 
23115a1e936bSStefano Zampini   PetscFunctionBegin;
23129566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
23139566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
231448a46eb9SPierre Jolivet   if (isascii) PetscCall(PetscViewerASCIIPrintf(viewer, "BDDC interface preconditioner\n"));
23159566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushTab(viewer));
23169566063dSJacob Faibussowitsch   PetscCall(PCView(bddcipc_ctx->bddc, viewer));
23179566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopTab(viewer));
23183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23195a1e936bSStefano Zampini }
23205a1e936bSStefano Zampini 
PCSetUp_BDDCIPC(PC pc)2321d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetUp_BDDCIPC(PC pc)
2322d71ae5a4SJacob Faibussowitsch {
23235a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
23245a1e936bSStefano Zampini   PetscBool   isbddc;
23255a1e936bSStefano Zampini   Vec         vv;
23265a1e936bSStefano Zampini   IS          is;
23275a1e936bSStefano Zampini   PC_IS      *pcis;
23285a1e936bSStefano Zampini 
23295a1e936bSStefano Zampini   PetscFunctionBegin;
23309566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
23319566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)bddcipc_ctx->bddc, PCBDDC, &isbddc));
233228b400f6SJacob Faibussowitsch   PetscCheck(isbddc, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Invalid type %s. Must be of type bddc", ((PetscObject)bddcipc_ctx->bddc)->type_name);
23339566063dSJacob Faibussowitsch   PetscCall(PCSetUp(bddcipc_ctx->bddc));
23345a1e936bSStefano Zampini 
23355a1e936bSStefano Zampini   /* create interface scatter */
2336f4f49eeaSPierre Jolivet   pcis = (PC_IS *)bddcipc_ctx->bddc->data;
23379566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l));
23389566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(pc->pmat, &vv, NULL));
23399566063dSJacob Faibussowitsch   PetscCall(ISRenumber(pcis->is_B_global, NULL, NULL, &is));
23409566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(vv, is, pcis->vec1_B, NULL, &bddcipc_ctx->g2l));
23419566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
23429566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&vv));
23433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23445a1e936bSStefano Zampini }
23455a1e936bSStefano Zampini 
PCApply_BDDCIPC(PC pc,Vec r,Vec x)2346d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_BDDCIPC(PC pc, Vec r, Vec x)
2347d71ae5a4SJacob Faibussowitsch {
23485a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
23495a1e936bSStefano Zampini   PC_IS      *pcis;
23505a1e936bSStefano Zampini   VecScatter  tmps;
23515a1e936bSStefano Zampini 
23525a1e936bSStefano Zampini   PetscFunctionBegin;
23539566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
2354f4f49eeaSPierre Jolivet   pcis              = (PC_IS *)bddcipc_ctx->bddc->data;
23555a1e936bSStefano Zampini   tmps              = pcis->global_to_B;
23565a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
23579566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc, r, pcis->vec1_B));
23589566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc, PETSC_FALSE));
23599566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc, pcis->vec1_B, x));
23605a1e936bSStefano Zampini   pcis->global_to_B = tmps;
23613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23625a1e936bSStefano Zampini }
23635a1e936bSStefano Zampini 
PCApplyTranspose_BDDCIPC(PC pc,Vec r,Vec x)2364d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_BDDCIPC(PC pc, Vec r, Vec x)
2365d71ae5a4SJacob Faibussowitsch {
23665a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
23675a1e936bSStefano Zampini   PC_IS      *pcis;
23685a1e936bSStefano Zampini   VecScatter  tmps;
23695a1e936bSStefano Zampini 
23705a1e936bSStefano Zampini   PetscFunctionBegin;
23719566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
2372f4f49eeaSPierre Jolivet   pcis              = (PC_IS *)bddcipc_ctx->bddc->data;
23735a1e936bSStefano Zampini   tmps              = pcis->global_to_B;
23745a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
23759566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc, r, pcis->vec1_B));
23769566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc, PETSC_TRUE));
23779566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc, pcis->vec1_B, x));
23785a1e936bSStefano Zampini   pcis->global_to_B = tmps;
23793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23805a1e936bSStefano Zampini }
23815a1e936bSStefano Zampini 
PCDestroy_BDDCIPC(PC pc)2382d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_BDDCIPC(PC pc)
2383d71ae5a4SJacob Faibussowitsch {
23845a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
23855a1e936bSStefano Zampini 
23865a1e936bSStefano Zampini   PetscFunctionBegin;
23879566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
23889566063dSJacob Faibussowitsch   PetscCall(PCDestroy(&bddcipc_ctx->bddc));
23899566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l));
23909566063dSJacob Faibussowitsch   PetscCall(PetscFree(bddcipc_ctx));
23913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23925a1e936bSStefano Zampini }
23935a1e936bSStefano Zampini 
23943425bc38SStefano Zampini /*@
23950f202f7eSStefano Zampini   PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system
23963425bc38SStefano Zampini 
23973425bc38SStefano Zampini   Collective
23983425bc38SStefano Zampini 
23993425bc38SStefano Zampini   Input Parameters:
240020f4b53cSBarry Smith + fetidp_mat      - the FETI-DP matrix obtained by a call to `PCBDDCCreateFETIDPOperators()`
2401f1580f4eSBarry Smith - fetidp_flux_sol - the solution of the FETI-DP linear system`
24023425bc38SStefano Zampini 
2403f1580f4eSBarry Smith   Output Parameter:
24040f202f7eSStefano Zampini . standard_sol - the solution defined on the physical domain
24053425bc38SStefano Zampini 
24063425bc38SStefano Zampini   Level: developer
24073425bc38SStefano Zampini 
2408f6cc42faSStefano Zampini   Note:
2409f6cc42faSStefano Zampini   Most users should employ the `KSP` interface for linear solvers and create a solver of type `KSPFETIDP`.
2410f6cc42faSStefano Zampini 
2411562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCCreateFETIDPOperators()`, `PCBDDCMatFETIDPGetRHS()`
24123425bc38SStefano Zampini @*/
PCBDDCMatFETIDPGetSolution(Mat fetidp_mat,Vec fetidp_flux_sol,Vec standard_sol)2413d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
2414d71ae5a4SJacob Faibussowitsch {
2415674ae819SStefano Zampini   FETIDPMat_ctx mat_ctx;
24163425bc38SStefano Zampini 
24173425bc38SStefano Zampini   PetscFunctionBegin;
2418266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat, MAT_CLASSID, 1);
2419266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_sol, VEC_CLASSID, 2);
2420266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_sol, VEC_CLASSID, 3);
24219566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx));
2422cac4c232SBarry Smith   PetscUseMethod(mat_ctx->pc, "PCBDDCMatFETIDPGetSolution_C", (Mat, Vec, Vec), (fetidp_mat, fetidp_flux_sol, standard_sol));
24233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24243425bc38SStefano Zampini }
24251e6b0712SBarry Smith 
MatISSubMatrixEmbedLocalIS(Mat A,IS oldis,IS * newis)2426d4371de1SStefano Zampini static PetscErrorCode MatISSubMatrixEmbedLocalIS(Mat A, IS oldis, IS *newis)
2427d4371de1SStefano Zampini {
2428d4371de1SStefano Zampini   Mat_IS                *matis = (Mat_IS *)A->data;
2429d4371de1SStefano Zampini   ISLocalToGlobalMapping ltog;
2430d4371de1SStefano Zampini   IS                     is;
2431d4371de1SStefano Zampini 
2432d4371de1SStefano Zampini   PetscFunctionBegin;
2433d4371de1SStefano Zampini   PetscCheck(matis->getsub_ris, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Missing getsub IS");
2434d4371de1SStefano Zampini   PetscCall(ISLocalToGlobalMappingCreateIS(matis->getsub_ris, &ltog));
2435d4371de1SStefano Zampini   PetscCall(ISGlobalToLocalMappingApplyIS(ltog, IS_GTOLM_DROP, oldis, &is));
2436d4371de1SStefano Zampini   PetscCall(ISOnComm(is, PetscObjectComm((PetscObject)A), PETSC_COPY_VALUES, newis));
2437d4371de1SStefano Zampini   PetscCall(ISLocalToGlobalMappingDestroy(&ltog));
2438d4371de1SStefano Zampini   PetscCall(ISDestroy(&is));
2439d4371de1SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2440d4371de1SStefano Zampini }
2441d4371de1SStefano Zampini 
PCBDDCCreateFETIDPOperators_BDDC(PC pc,PetscBool fully_redundant,const char * prefix,Mat * fetidp_mat,PC * fetidp_pc)2442d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc)
2443d71ae5a4SJacob Faibussowitsch {
2444674ae819SStefano Zampini   FETIDPMat_ctx fetidpmat_ctx;
24453425bc38SStefano Zampini   Mat           newmat;
2446674ae819SStefano Zampini   FETIDPPC_ctx  fetidppc_ctx;
24473425bc38SStefano Zampini   PC            newpc;
2448ce94432eSBarry Smith   MPI_Comm      comm;
24493425bc38SStefano Zampini 
24503425bc38SStefano Zampini   PetscFunctionBegin;
24519566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)pc, &comm));
245215579a77SStefano Zampini   /* FETI-DP matrix */
24539566063dSJacob Faibussowitsch   PetscCall(PCBDDCCreateFETIDPMatContext(pc, &fetidpmat_ctx));
24541720468bSStefano Zampini   fetidpmat_ctx->fully_redundant = fully_redundant;
24559566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetupFETIDPMatContext(fetidpmat_ctx));
24569566063dSJacob Faibussowitsch   PetscCall(MatCreateShell(comm, fetidpmat_ctx->n, fetidpmat_ctx->n, fetidpmat_ctx->N, fetidpmat_ctx->N, fetidpmat_ctx, &newmat));
24579566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)newmat, !fetidpmat_ctx->l2g_lambda_only ? "F" : "G"));
245857d50842SBarry Smith   PetscCall(MatShellSetOperation(newmat, MATOP_MULT, (PetscErrorCodeFn *)FETIDPMatMult));
245957d50842SBarry Smith   PetscCall(MatShellSetOperation(newmat, MATOP_MULT_TRANSPOSE, (PetscErrorCodeFn *)FETIDPMatMultTranspose));
246057d50842SBarry Smith   PetscCall(MatShellSetOperation(newmat, MATOP_DESTROY, (PetscErrorCodeFn *)PCBDDCDestroyFETIDPMat));
246115579a77SStefano Zampini   /* propagate MatOptions */
246215579a77SStefano Zampini   {
246315579a77SStefano Zampini     PC_BDDC  *pcbddc = (PC_BDDC *)fetidpmat_ctx->pc->data;
2464b94d7dedSBarry Smith     PetscBool isset, issym;
246515579a77SStefano Zampini 
2466b94d7dedSBarry Smith     PetscCall(MatIsSymmetricKnown(pc->mat, &isset, &issym));
2467b94d7dedSBarry Smith     if ((isset && issym) || pcbddc->symmetric_primal) PetscCall(MatSetOption(newmat, MAT_SYMMETRIC, PETSC_TRUE));
246815579a77SStefano Zampini   }
24699566063dSJacob Faibussowitsch   PetscCall(MatSetOptionsPrefix(newmat, prefix));
24709566063dSJacob Faibussowitsch   PetscCall(MatAppendOptionsPrefix(newmat, "fetidp_"));
24719566063dSJacob Faibussowitsch   PetscCall(MatSetUp(newmat));
247215579a77SStefano Zampini   /* FETI-DP preconditioner */
24739566063dSJacob Faibussowitsch   PetscCall(PCBDDCCreateFETIDPPCContext(pc, &fetidppc_ctx));
24749566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetupFETIDPPCContext(newmat, fetidppc_ctx));
24759566063dSJacob Faibussowitsch   PetscCall(PCCreate(comm, &newpc));
24769566063dSJacob Faibussowitsch   PetscCall(PCSetOperators(newpc, newmat, newmat));
24779566063dSJacob Faibussowitsch   PetscCall(PCSetOptionsPrefix(newpc, prefix));
24789566063dSJacob Faibussowitsch   PetscCall(PCAppendOptionsPrefix(newpc, "fetidp_"));
24799566063dSJacob Faibussowitsch   PetscCall(PCSetErrorIfFailure(newpc, pc->erroriffailure));
248015579a77SStefano Zampini   if (!fetidpmat_ctx->l2g_lambda_only) { /* standard FETI-DP */
24819566063dSJacob Faibussowitsch     PetscCall(PCSetType(newpc, PCSHELL));
24829566063dSJacob Faibussowitsch     PetscCall(PCShellSetName(newpc, "FETI-DP multipliers"));
24839566063dSJacob Faibussowitsch     PetscCall(PCShellSetContext(newpc, fetidppc_ctx));
24849566063dSJacob Faibussowitsch     PetscCall(PCShellSetApply(newpc, FETIDPPCApply));
24859566063dSJacob Faibussowitsch     PetscCall(PCShellSetApplyTranspose(newpc, FETIDPPCApplyTranspose));
24869566063dSJacob Faibussowitsch     PetscCall(PCShellSetView(newpc, FETIDPPCView));
24879566063dSJacob Faibussowitsch     PetscCall(PCShellSetDestroy(newpc, PCBDDCDestroyFETIDPPC));
24885a1e936bSStefano Zampini   } else { /* saddle-point FETI-DP */
24895a1e936bSStefano Zampini     Mat       M;
24905a1e936bSStefano Zampini     PetscInt  psize;
24915a1e936bSStefano Zampini     PetscBool fake = PETSC_FALSE, isfieldsplit;
2492e1214c54Sstefano_zampini 
24939566063dSJacob Faibussowitsch     PetscCall(ISViewFromOptions(fetidpmat_ctx->lagrange, NULL, "-lag_view"));
24949566063dSJacob Faibussowitsch     PetscCall(ISViewFromOptions(fetidpmat_ctx->pressure, NULL, "-press_view"));
24959566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_PPmat", (PetscObject *)&M));
24969566063dSJacob Faibussowitsch     PetscCall(PCSetType(newpc, PCFIELDSPLIT));
24979566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetIS(newpc, "lag", fetidpmat_ctx->lagrange));
24989566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetIS(newpc, "p", fetidpmat_ctx->pressure));
24999566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetType(newpc, PC_COMPOSITE_SCHUR));
25009566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetSchurFactType(newpc, PC_FIELDSPLIT_SCHUR_FACT_DIAG));
25019566063dSJacob Faibussowitsch     PetscCall(ISGetSize(fetidpmat_ctx->pressure, &psize));
25025a1e936bSStefano Zampini     if (psize != M->rmap->N) {
25035a1e936bSStefano Zampini       Mat      M2;
25045a1e936bSStefano Zampini       PetscInt lpsize;
25055a1e936bSStefano Zampini 
25065a1e936bSStefano Zampini       fake = PETSC_TRUE;
25079566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(fetidpmat_ctx->pressure, &lpsize));
25089566063dSJacob Faibussowitsch       PetscCall(MatCreate(comm, &M2));
25099566063dSJacob Faibussowitsch       PetscCall(MatSetType(M2, MATAIJ));
25109566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(M2, lpsize, lpsize, psize, psize));
25119566063dSJacob Faibussowitsch       PetscCall(MatSetUp(M2));
25129566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(M2, MAT_FINAL_ASSEMBLY));
25139566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(M2, MAT_FINAL_ASSEMBLY));
25149566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSetSchurPre(newpc, PC_FIELDSPLIT_SCHUR_PRE_USER, M2));
25159566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&M2));
25165a1e936bSStefano Zampini     } else {
25179566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSetSchurPre(newpc, PC_FIELDSPLIT_SCHUR_PRE_USER, M));
25185a1e936bSStefano Zampini     }
25199566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetSchurScale(newpc, 1.0));
252015579a77SStefano Zampini 
252115579a77SStefano Zampini     /* we need to setfromoptions and setup here to access the blocks */
25229566063dSJacob Faibussowitsch     PetscCall(PCSetFromOptions(newpc));
25239566063dSJacob Faibussowitsch     PetscCall(PCSetUp(newpc));
2524e1214c54Sstefano_zampini 
25255a1e936bSStefano Zampini     /* user may have changed the type (e.g. -fetidp_pc_type none) */
25269566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)newpc, PCFIELDSPLIT, &isfieldsplit));
25275a1e936bSStefano Zampini     if (isfieldsplit) {
25285a1e936bSStefano Zampini       KSP      *ksps;
25295a1e936bSStefano Zampini       PC        ppc, lagpc;
25305a1e936bSStefano Zampini       PetscInt  nn;
2531064a4176SStefano Zampini       PetscBool ismatis, matisok = PETSC_FALSE, check = PETSC_FALSE;
25325a1e936bSStefano Zampini 
2533e1214c54Sstefano_zampini       /* set the solver for the (0,0) block */
25349566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSchurGetSubKSP(newpc, &nn, &ksps));
25355a1e936bSStefano Zampini       if (!nn) { /* not of type PC_COMPOSITE_SCHUR */
25369566063dSJacob Faibussowitsch         PetscCall(PCFieldSplitGetSubKSP(newpc, &nn, &ksps));
25375a1e936bSStefano Zampini         if (!fake) { /* pass pmat to the pressure solver */
25385a1e936bSStefano Zampini           Mat F;
25395a1e936bSStefano Zampini 
25409566063dSJacob Faibussowitsch           PetscCall(KSPGetOperators(ksps[1], &F, NULL));
25419566063dSJacob Faibussowitsch           PetscCall(KSPSetOperators(ksps[1], F, M));
25425a1e936bSStefano Zampini         }
25435a1e936bSStefano Zampini       } else {
2544b94d7dedSBarry Smith         PetscBool issym, isset;
25455a1e936bSStefano Zampini         Mat       S;
25465a1e936bSStefano Zampini 
25479566063dSJacob Faibussowitsch         PetscCall(PCFieldSplitSchurGetS(newpc, &S));
2548b94d7dedSBarry Smith         PetscCall(MatIsSymmetricKnown(newmat, &isset, &issym));
2549b94d7dedSBarry Smith         if (isset) PetscCall(MatSetOption(S, MAT_SYMMETRIC, issym));
25505a1e936bSStefano Zampini       }
25519566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksps[0], &lagpc));
25529566063dSJacob Faibussowitsch       PetscCall(PCSetType(lagpc, PCSHELL));
25539566063dSJacob Faibussowitsch       PetscCall(PCShellSetName(lagpc, "FETI-DP multipliers"));
25549566063dSJacob Faibussowitsch       PetscCall(PCShellSetContext(lagpc, fetidppc_ctx));
25559566063dSJacob Faibussowitsch       PetscCall(PCShellSetApply(lagpc, FETIDPPCApply));
25569566063dSJacob Faibussowitsch       PetscCall(PCShellSetApplyTranspose(lagpc, FETIDPPCApplyTranspose));
25579566063dSJacob Faibussowitsch       PetscCall(PCShellSetView(lagpc, FETIDPPCView));
25589566063dSJacob Faibussowitsch       PetscCall(PCShellSetDestroy(lagpc, PCBDDCDestroyFETIDPPC));
25595a1e936bSStefano Zampini 
25605a1e936bSStefano Zampini       /* Olof's idea: interface Schur complement preconditioner for the mass matrix */
25619566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksps[1], &ppc));
25625a1e936bSStefano Zampini       if (fake) {
2563d4371de1SStefano Zampini         PC_BDDC       *pcbddc = (PC_BDDC *)fetidpmat_ctx->pc->data;
25645a1e936bSStefano Zampini         BDDCIPC_ctx    bddcipc_ctx;
2565ff11fd76SStefano Zampini         PetscContainer c;
25665a1e936bSStefano Zampini 
25675a1e936bSStefano Zampini         matisok = PETSC_TRUE;
25685a1e936bSStefano Zampini 
25695a1e936bSStefano Zampini         /* create inner BDDC solver */
25709566063dSJacob Faibussowitsch         PetscCall(PetscNew(&bddcipc_ctx));
25719566063dSJacob Faibussowitsch         PetscCall(PCCreate(comm, &bddcipc_ctx->bddc));
25729566063dSJacob Faibussowitsch         PetscCall(PCSetType(bddcipc_ctx->bddc, PCBDDC));
25739566063dSJacob Faibussowitsch         PetscCall(PCSetOperators(bddcipc_ctx->bddc, M, M));
2574d4371de1SStefano Zampini         PetscCall(PetscObjectTypeCompare((PetscObject)M, MATIS, &ismatis));
2575d4371de1SStefano Zampini         PetscCheck(ismatis, comm, PETSC_ERR_PLIB, "Matrix type %s not of type MATIS", ((PetscObject)M)->type_name);
2576d4371de1SStefano Zampini         /* the inner bddc for FETI-DP is already setup, we have local info available */
2577d4371de1SStefano Zampini         if (pcbddc->user_primal_vertices_local || pcbddc->n_ISForDofsLocal > 2) {
2578d4371de1SStefano Zampini           if (pcbddc->user_primal_vertices_local) {
2579d4371de1SStefano Zampini             IS primals;
2580d4371de1SStefano Zampini 
2581d4371de1SStefano Zampini             PetscCall(MatISSubMatrixEmbedLocalIS(M, pcbddc->user_primal_vertices_local, &primals));
2582d4371de1SStefano Zampini             PetscCall(PCBDDCSetPrimalVerticesLocalIS(bddcipc_ctx->bddc, primals));
2583d4371de1SStefano Zampini             PetscCall(ISDestroy(&primals));
2584d4371de1SStefano Zampini           }
2585d4371de1SStefano Zampini           if (pcbddc->n_ISForDofsLocal > 2) { /* no need to propagate info if nfields < 3 */
2586d4371de1SStefano Zampini             IS      *split;
2587d4371de1SStefano Zampini             PetscInt i, nf;
2588d4371de1SStefano Zampini 
2589d4371de1SStefano Zampini             PetscCall(PetscCalloc1(pcbddc->n_ISForDofsLocal, &split));
2590d4371de1SStefano Zampini             for (i = 0, nf = 0; i < pcbddc->n_ISForDofsLocal; i++) {
2591d4371de1SStefano Zampini               PetscInt ns;
2592d4371de1SStefano Zampini 
2593d4371de1SStefano Zampini               PetscCall(MatISSubMatrixEmbedLocalIS(M, pcbddc->ISForDofsLocal[i], &split[nf]));
2594d4371de1SStefano Zampini               PetscCall(ISGetSize(split[nf], &ns));
2595d4371de1SStefano Zampini               if (!ns) PetscCall(ISDestroy(&split[nf]));
2596d4371de1SStefano Zampini               else nf++;
2597d4371de1SStefano Zampini             }
2598d4371de1SStefano Zampini             PetscCall(PCBDDCSetDofsSplittingLocal(bddcipc_ctx->bddc, nf, split));
2599d4371de1SStefano Zampini             for (i = 0; i < nf; i++) PetscCall(ISDestroy(&split[i]));
2600d4371de1SStefano Zampini             PetscCall(PetscFree(split));
2601d4371de1SStefano Zampini           }
2602d4371de1SStefano Zampini         }
26039566063dSJacob Faibussowitsch         PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_pCSR", (PetscObject *)&c));
26049566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)M, MATIS, &ismatis));
2605ff11fd76SStefano Zampini         if (c && ismatis) {
2606ff11fd76SStefano Zampini           Mat       lM;
2607ff11fd76SStefano Zampini           PetscInt *csr, n;
2608ff11fd76SStefano Zampini 
26099566063dSJacob Faibussowitsch           PetscCall(MatISGetLocalMat(M, &lM));
26109566063dSJacob Faibussowitsch           PetscCall(MatGetSize(lM, &n, NULL));
2611*2a8381b2SBarry Smith           PetscCall(PetscContainerGetPointer(c, &csr));
26129566063dSJacob Faibussowitsch           PetscCall(PCBDDCSetLocalAdjacencyGraph(bddcipc_ctx->bddc, n, csr, csr + (n + 1), PETSC_COPY_VALUES));
26139566063dSJacob Faibussowitsch           PetscCall(MatISRestoreLocalMat(M, &lM));
2614ff11fd76SStefano Zampini         }
26159566063dSJacob Faibussowitsch         PetscCall(PCSetOptionsPrefix(bddcipc_ctx->bddc, ((PetscObject)ksps[1])->prefix));
26169566063dSJacob Faibussowitsch         PetscCall(PCSetErrorIfFailure(bddcipc_ctx->bddc, pc->erroriffailure));
26179566063dSJacob Faibussowitsch         PetscCall(PCSetFromOptions(bddcipc_ctx->bddc));
26185a1e936bSStefano Zampini 
26195a1e936bSStefano Zampini         /* wrap the interface application */
26209566063dSJacob Faibussowitsch         PetscCall(PCSetType(ppc, PCSHELL));
26219566063dSJacob Faibussowitsch         PetscCall(PCShellSetName(ppc, "FETI-DP pressure"));
26229566063dSJacob Faibussowitsch         PetscCall(PCShellSetContext(ppc, bddcipc_ctx));
26239566063dSJacob Faibussowitsch         PetscCall(PCShellSetSetUp(ppc, PCSetUp_BDDCIPC));
26249566063dSJacob Faibussowitsch         PetscCall(PCShellSetApply(ppc, PCApply_BDDCIPC));
26259566063dSJacob Faibussowitsch         PetscCall(PCShellSetApplyTranspose(ppc, PCApplyTranspose_BDDCIPC));
26269566063dSJacob Faibussowitsch         PetscCall(PCShellSetView(ppc, PCView_BDDCIPC));
26279566063dSJacob Faibussowitsch         PetscCall(PCShellSetDestroy(ppc, PCDestroy_BDDCIPC));
26285a1e936bSStefano Zampini       }
26295a1e936bSStefano Zampini 
26305a1e936bSStefano Zampini       /* determine if we need to assemble M to construct a preconditioner */
26315a1e936bSStefano Zampini       if (!matisok) {
26329566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)M, MATIS, &ismatis));
26339566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompareAny((PetscObject)ppc, &matisok, PCBDDC, PCJACOBI, PCNONE, PCMG, ""));
263448a46eb9SPierre Jolivet         if (ismatis && !matisok) PetscCall(MatConvert(M, MATAIJ, MAT_INPLACE_MATRIX, &M));
26355a1e936bSStefano Zampini       }
2636064a4176SStefano Zampini 
2637064a4176SStefano Zampini       /* run the subproblems to check convergence */
26389566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)newmat)->prefix, "-check_saddlepoint", &check, NULL));
2639064a4176SStefano Zampini       if (check) {
2640064a4176SStefano Zampini         PetscInt i;
2641064a4176SStefano Zampini 
2642064a4176SStefano Zampini         for (i = 0; i < nn; i++) {
2643064a4176SStefano Zampini           KSP       kspC;
2644e8f11ae9SBarry Smith           PC        npc;
2645064a4176SStefano Zampini           Mat       F, pF;
2646064a4176SStefano Zampini           Vec       x, y;
2647064a4176SStefano Zampini           PetscBool isschur, prec = PETSC_TRUE;
2648064a4176SStefano Zampini 
26499566063dSJacob Faibussowitsch           PetscCall(KSPCreate(PetscObjectComm((PetscObject)ksps[i]), &kspC));
26503821be0aSBarry Smith           PetscCall(KSPSetNestLevel(kspC, pc->kspnestlevel));
26519566063dSJacob Faibussowitsch           PetscCall(KSPSetOptionsPrefix(kspC, ((PetscObject)ksps[i])->prefix));
26529566063dSJacob Faibussowitsch           PetscCall(KSPAppendOptionsPrefix(kspC, "check_"));
26539566063dSJacob Faibussowitsch           PetscCall(KSPGetOperators(ksps[i], &F, &pF));
26549566063dSJacob Faibussowitsch           PetscCall(PetscObjectTypeCompare((PetscObject)F, MATSCHURCOMPLEMENT, &isschur));
2655064a4176SStefano Zampini           if (isschur) {
2656064a4176SStefano Zampini             KSP  kspS, kspS2;
2657064a4176SStefano Zampini             Mat  A00, pA00, A10, A01, A11;
2658064a4176SStefano Zampini             char prefix[256];
2659064a4176SStefano Zampini 
26609566063dSJacob Faibussowitsch             PetscCall(MatSchurComplementGetKSP(F, &kspS));
26619566063dSJacob Faibussowitsch             PetscCall(MatSchurComplementGetSubMatrices(F, &A00, &pA00, &A01, &A10, &A11));
26629566063dSJacob Faibussowitsch             PetscCall(MatCreateSchurComplement(A00, pA00, A01, A10, A11, &F));
26639566063dSJacob Faibussowitsch             PetscCall(MatSchurComplementGetKSP(F, &kspS2));
26649566063dSJacob Faibussowitsch             PetscCall(PetscSNPrintf(prefix, sizeof(prefix), "%sschur_", ((PetscObject)kspC)->prefix));
26659566063dSJacob Faibussowitsch             PetscCall(KSPSetOptionsPrefix(kspS2, prefix));
2666e8f11ae9SBarry Smith             PetscCall(KSPGetPC(kspS2, &npc));
2667e8f11ae9SBarry Smith             PetscCall(PCSetType(npc, PCKSP));
2668e8f11ae9SBarry Smith             PetscCall(PCKSPSetKSP(npc, kspS));
26699566063dSJacob Faibussowitsch             PetscCall(KSPSetFromOptions(kspS2));
2670e8f11ae9SBarry Smith             PetscCall(KSPGetPC(kspS2, &npc));
2671e8f11ae9SBarry Smith             PetscCall(PCSetUseAmat(npc, PETSC_TRUE));
2672064a4176SStefano Zampini           } else {
26739566063dSJacob Faibussowitsch             PetscCall(PetscObjectReference((PetscObject)F));
2674064a4176SStefano Zampini           }
26759566063dSJacob Faibussowitsch           PetscCall(KSPSetFromOptions(kspC));
26769566063dSJacob Faibussowitsch           PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)kspC)->prefix, "-preconditioned", &prec, NULL));
2677064a4176SStefano Zampini           if (prec) {
2678e8f11ae9SBarry Smith             PetscCall(KSPGetPC(ksps[i], &npc));
2679e8f11ae9SBarry Smith             PetscCall(KSPSetPC(kspC, npc));
2680064a4176SStefano Zampini           }
26819566063dSJacob Faibussowitsch           PetscCall(KSPSetOperators(kspC, F, pF));
26829566063dSJacob Faibussowitsch           PetscCall(MatCreateVecs(F, &x, &y));
26839566063dSJacob Faibussowitsch           PetscCall(VecSetRandom(x, NULL));
26849566063dSJacob Faibussowitsch           PetscCall(MatMult(F, x, y));
26859566063dSJacob Faibussowitsch           PetscCall(KSPSolve(kspC, y, x));
2686e8f11ae9SBarry Smith           PetscCall(KSPCheckSolve(kspC, npc, x));
26879566063dSJacob Faibussowitsch           PetscCall(KSPDestroy(&kspC));
26889566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&F));
26899566063dSJacob Faibussowitsch           PetscCall(VecDestroy(&x));
26909566063dSJacob Faibussowitsch           PetscCall(VecDestroy(&y));
2691064a4176SStefano Zampini         }
2692064a4176SStefano Zampini       }
26939566063dSJacob Faibussowitsch       PetscCall(PetscFree(ksps));
2694e1214c54Sstefano_zampini     }
26955a1e936bSStefano Zampini   }
26963425bc38SStefano Zampini   /* return pointers for objects created */
26973425bc38SStefano Zampini   *fetidp_mat = newmat;
26983425bc38SStefano Zampini   *fetidp_pc  = newpc;
26993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27003425bc38SStefano Zampini }
27011e6b0712SBarry Smith 
270294ef8ddeSSatish Balay /*@C
27030f202f7eSStefano Zampini   PCBDDCCreateFETIDPOperators - Create FETI-DP operators
27043425bc38SStefano Zampini 
27053425bc38SStefano Zampini   Collective
27063425bc38SStefano Zampini 
27073425bc38SStefano Zampini   Input Parameters:
270898ad52f2SBarry Smith + pc              - the `PCBDDC` preconditioning context (setup should have been called before)
2709547c9a8eSstefano_zampini . fully_redundant - true for a fully redundant set of Lagrange multipliers
271020f4b53cSBarry Smith - prefix          - optional options database prefix for the objects to be created (can be `NULL`)
271128509bceSStefano Zampini 
271228509bceSStefano Zampini   Output Parameters:
27130f202f7eSStefano Zampini + fetidp_mat - shell FETI-DP matrix object
27140f202f7eSStefano Zampini - fetidp_pc  - shell Dirichlet preconditioner for FETI-DP matrix
271528509bceSStefano Zampini 
27163425bc38SStefano Zampini   Level: developer
27173425bc38SStefano Zampini 
2718f6cc42faSStefano Zampini   Notes:
2719f6cc42faSStefano Zampini   Most users should employ the `KSP` interface for linear solvers and create a solver of type `KSPFETIDP`.
2720f6cc42faSStefano Zampini   Currently the only operations provided for the FETI-DP matrix are `MatMult()` and `MatMultTranspose()`
27213425bc38SStefano Zampini 
2722f6cc42faSStefano Zampini .seealso: [](ch_ksp), `KSPFETIDP`, `PCBDDC`, `PCBDDCMatFETIDPGetRHS()`, `PCBDDCMatFETIDPGetSolution()`
27233425bc38SStefano Zampini @*/
PCBDDCCreateFETIDPOperators(PC pc,PetscBool fully_redundant,const char * prefix,Mat * fetidp_mat,PC * fetidp_pc)2724d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc)
2725d71ae5a4SJacob Faibussowitsch {
27263425bc38SStefano Zampini   PetscFunctionBegin;
27273425bc38SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
27280fdf79fbSJacob Faibussowitsch   PetscCheck(pc->setupcalled, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "You must call PCSetup_BDDC() first");
2729cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCCreateFETIDPOperators_C", (PC, PetscBool, const char *, Mat *, PC *), (pc, fully_redundant, prefix, fetidp_mat, fetidp_pc));
27303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27313425bc38SStefano Zampini }
2732f1580f4eSBarry Smith 
2733da1bb401SStefano Zampini /*MC
27341d27aa22SBarry Smith    PCBDDC - Balancing Domain Decomposition by Constraints preconditioners, {cite}`dohrmann2007approximate`, {cite}`klawonn2006dual`, {cite}`mandel2008multispace`
27350c7d97c5SJed Brown 
2736f1580f4eSBarry Smith    Requires `MATIS` matrices (Pmat) with local matrices (inside the `MATIS`) of type `MATSEQAIJ`, `MATSEQBAIJ` or `MATSEQSBAIJ`
273728509bceSStefano Zampini 
27380b4b7b1cSBarry Smith    Works with unsymmetric and indefinite problems.
273928509bceSStefano Zampini 
2740f1580f4eSBarry Smith    Unlike 'conventional' interface preconditioners, `PCBDDC` iterates over all degrees of freedom, not just those on the interface. This allows the use
2741f1580f4eSBarry Smith    of approximate solvers on the subdomains.
2742b6fdb6dfSStefano Zampini 
27431d27aa22SBarry Smith    Approximate local solvers are automatically adapted (see {cite}`dohrmann2007approximate`,) if the user has attached a nullspace object to the subdomain matrices, and informed
2744f1580f4eSBarry Smith    `PCBDDC` of using approximate solvers (via the command line).
274528509bceSStefano Zampini 
27460b4b7b1cSBarry Smith    Boundary nodes are split into vertices, edges and faces classes using information from the local to global mapping of dofs and the local connectivity graph of nodes.
2747f1580f4eSBarry Smith    The latter can be customized by using `PCBDDCSetLocalAdjacencyGraph()`
274828509bceSStefano Zampini 
2749f1580f4eSBarry Smith    Additional information on dofs can be provided by using `PCBDDCSetDofsSplitting()`, `PCBDDCSetDirichletBoundaries()`, `PCBDDCSetNeumannBoundaries()`, and
2750f1580f4eSBarry Smith    `PCBDDCSetPrimalVerticesIS()` and their local counterparts.
275128509bceSStefano Zampini 
2752f1580f4eSBarry Smith    Constraints can be customized by attaching a `MatNullSpace` object to the `MATIS` matrix via `MatSetNearNullSpace()`. Non-singular modes are retained via SVD.
275328509bceSStefano Zampini 
27541d27aa22SBarry Smith    Change of basis is performed similarly to {cite}`klawonn2006dual` when requested. When more than one constraint is present on a single connected component
2755f1580f4eSBarry Smith    (i.e. an edge or a face), a robust method based on local QR factorizations is used.
2756f1580f4eSBarry Smith    User defined change of basis can be passed to `PCBDDC` with `PCBDDCSetChangeOfBasisMat()`
275728509bceSStefano Zampini 
27581d27aa22SBarry Smith    The PETSc implementation also supports multilevel `PCBDDC` {cite}`mandel2008multispace`. Coarse grids are partitioned using a `MatPartitioning` object.
275928509bceSStefano Zampini 
27601d27aa22SBarry Smith    Adaptive selection of primal constraints is supported for SPD systems with high-contrast in the coefficients if MUMPS or MKL_PARDISO are present.
27610f202f7eSStefano Zampini 
2762f1580f4eSBarry Smith    Options Database Keys:
2763a2b725a8SWilliam Gropp +    -pc_bddc_use_vertices <true>         - use or not vertices in primal space
27640f202f7eSStefano Zampini .    -pc_bddc_use_edges <true>            - use or not edges in primal space
27650f202f7eSStefano Zampini .    -pc_bddc_use_faces <false>           - use or not faces in primal space
27660f202f7eSStefano Zampini .    -pc_bddc_symmetric <true>            - symmetric computation of primal basis functions. Specify false for unsymmetric problems
27670f202f7eSStefano Zampini .    -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only)
27680f202f7eSStefano Zampini .    -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested
27690f202f7eSStefano Zampini .    -pc_bddc_switch_static <false>       - switches from M_2 (default) to M_3 operator (see reference article [1])
277028509bceSStefano Zampini .    -pc_bddc_levels <0>                  - maximum number of levels for multilevel
27710f202f7eSStefano 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)
27725459c157SBarry 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)
27730f202f7eSStefano Zampini .    -pc_bddc_use_deluxe_scaling <false>  - use deluxe scaling
277471f2caa7Sprj- .    -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)
2775bd2a564bSStefano 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)
277628509bceSStefano Zampini -    -pc_bddc_check_level <0>             - set verbosity level of debugging output
277728509bceSStefano Zampini 
2778f1580f4eSBarry Smith    Options for Dirichlet, Neumann or coarse solver can be set using the appropriate options prefix
277928509bceSStefano Zampini .vb
278028509bceSStefano Zampini       -pc_bddc_dirichlet_
278128509bceSStefano Zampini       -pc_bddc_neumann_
278228509bceSStefano Zampini       -pc_bddc_coarse_
278328509bceSStefano Zampini .ve
2784f1580f4eSBarry Smith    e.g. -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. `PCBDDC` uses by default `KSPPREONLY` and `PCLU`.
278528509bceSStefano Zampini 
2786f1580f4eSBarry Smith    When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified using the options prefix
278728509bceSStefano Zampini .vb
2788312be037SStefano Zampini       -pc_bddc_dirichlet_lN_
2789312be037SStefano Zampini       -pc_bddc_neumann_lN_
2790312be037SStefano Zampini       -pc_bddc_coarse_lN_
279128509bceSStefano Zampini .ve
27920f202f7eSStefano Zampini    Note that level number ranges from the finest (0) to the coarsest (N).
2793f1580f4eSBarry 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
2794f1580f4eSBarry Smith    to the option, e.g.
27950f202f7eSStefano Zampini .vb
27960f202f7eSStefano Zampini      -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3
27970f202f7eSStefano Zampini .ve
27980f202f7eSStefano 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
2799da1bb401SStefano Zampini 
2800da1bb401SStefano Zampini    Level: intermediate
2801da1bb401SStefano Zampini 
2802f6cc42faSStefano Zampini .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `MATIS`, `KSPFETIDP`, `PCLU`, `PCGAMG`, `PC`, `PCBDDCSetLocalAdjacencyGraph()`, `PCBDDCSetDofsSplitting()`,
2803f1580f4eSBarry Smith           `PCBDDCSetDirichletBoundaries()`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCSetPrimalVerticesIS()`, `MatNullSpace`, `MatSetNearNullSpace()`,
2804f1580f4eSBarry Smith           `PCBDDCSetChangeOfBasisMat()`, `PCBDDCCreateFETIDPOperators()`, `PCNN`
2805da1bb401SStefano Zampini M*/
2806b2573a8aSBarry Smith 
PCCreate_BDDC(PC pc)2807d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
2808d71ae5a4SJacob Faibussowitsch {
2809da1bb401SStefano Zampini   PC_BDDC *pcbddc;
2810da1bb401SStefano Zampini 
2811da1bb401SStefano Zampini   PetscFunctionBegin;
28124dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&pcbddc));
28133ec1f749SStefano Zampini   pc->data = pcbddc;
2814da1bb401SStefano Zampini 
281504c3f3b8SBarry Smith   PetscCall(PCISInitialize(pc));
2816da1bb401SStefano Zampini 
28179326c5c6Sstefano_zampini   /* create local graph structure */
28189566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphCreate(&pcbddc->mat_graph));
28199326c5c6Sstefano_zampini 
28209326c5c6Sstefano_zampini   /* BDDC nonzero defaults */
28216d9e27e4SStefano Zampini   pcbddc->use_nnsp                  = PETSC_TRUE;
282208a5cf49SStefano Zampini   pcbddc->use_local_adj             = PETSC_TRUE;
282347d04d0dSStefano Zampini   pcbddc->use_vertices              = PETSC_TRUE;
282447d04d0dSStefano Zampini   pcbddc->use_edges                 = PETSC_TRUE;
28253301b35fSStefano Zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
282614f95afaSStefano Zampini   pcbddc->vertex_size               = 1;
2827c703fcc7SStefano Zampini   pcbddc->recompute_topography      = PETSC_TRUE;
282868457ee5SStefano Zampini   pcbddc->coarse_size               = -1;
282985c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
283047d04d0dSStefano Zampini   pcbddc->coarsening_ratio          = 8;
283157de7509SStefano Zampini   pcbddc->coarse_eqs_per_proc       = 1;
283227b6a85dSStefano Zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
28331e0482f5SStefano Zampini   pcbddc->nedfield                  = -1;
28341e0482f5SStefano Zampini   pcbddc->nedglobal                 = PETSC_TRUE;
28351690c2aeSBarry Smith   pcbddc->graphmaxcount             = PETSC_INT_MAX;
2836b96c3477SStefano Zampini   pcbddc->sub_schurs_layers         = -1;
2837bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[0]     = 0.0;
2838bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[1]     = 0.0;
2839b7eb3628SStefano Zampini 
2840da1bb401SStefano Zampini   /* function pointers */
2841da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
284293bd9ae7SStefano Zampini   pc->ops->applytranspose      = PCApplyTranspose_BDDC;
2843da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
2844da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
2845da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
28466b78500eSPatrick Sanan   pc->ops->view                = PCView_BDDC;
28470a545947SLisandro Dalcin   pc->ops->applyrichardson     = NULL;
28480a545947SLisandro Dalcin   pc->ops->applysymmetricleft  = NULL;
28490a545947SLisandro Dalcin   pc->ops->applysymmetricright = NULL;
2850534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
2851534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
28529326c5c6Sstefano_zampini   pc->ops->reset               = PCReset_BDDC;
2853da1bb401SStefano Zampini 
2854da1bb401SStefano Zampini   /* composing function */
28559566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDiscreteGradient_C", PCBDDCSetDiscreteGradient_BDDC));
28569566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDivergenceMat_C", PCBDDCSetDivergenceMat_BDDC));
28579566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetChangeOfBasisMat_C", PCBDDCSetChangeOfBasisMat_BDDC));
28589566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesLocalIS_C", PCBDDCSetPrimalVerticesLocalIS_BDDC));
28599566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesIS_C", PCBDDCSetPrimalVerticesIS_BDDC));
28609566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesLocalIS_C", PCBDDCGetPrimalVerticesLocalIS_BDDC));
28619566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesIS_C", PCBDDCGetPrimalVerticesIS_BDDC));
28629566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetCoarseningRatio_C", PCBDDCSetCoarseningRatio_BDDC));
28639566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevel_C", PCBDDCSetLevel_BDDC));
28649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetUseExactDirichlet_C", PCBDDCSetUseExactDirichlet_BDDC));
28659566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevels_C", PCBDDCSetLevels_BDDC));
28669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundaries_C", PCBDDCSetDirichletBoundaries_BDDC));
28679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundariesLocal_C", PCBDDCSetDirichletBoundariesLocal_BDDC));
28689566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundaries_C", PCBDDCSetNeumannBoundaries_BDDC));
28699566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundariesLocal_C", PCBDDCSetNeumannBoundariesLocal_BDDC));
28709566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundaries_C", PCBDDCGetDirichletBoundaries_BDDC));
28719566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundariesLocal_C", PCBDDCGetDirichletBoundariesLocal_BDDC));
28729566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundaries_C", PCBDDCGetNeumannBoundaries_BDDC));
28739566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundariesLocal_C", PCBDDCGetNeumannBoundariesLocal_BDDC));
28749566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplitting_C", PCBDDCSetDofsSplitting_BDDC));
28759566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplittingLocal_C", PCBDDCSetDofsSplittingLocal_BDDC));
28769566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", PCBDDCSetLocalAdjacencyGraph_BDDC));
28779566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCCreateFETIDPOperators_C", PCBDDCCreateFETIDPOperators_BDDC));
28789566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetRHS_C", PCBDDCMatFETIDPGetRHS_BDDC));
28799566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetSolution_C", PCBDDCMatFETIDPGetSolution_BDDC));
28809566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", PCPreSolveChangeRHS_BDDC));
28819566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_BDDC));
28823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2883da1bb401SStefano Zampini }
288443371fb9SStefano Zampini 
288543371fb9SStefano Zampini /*@C
2886f1580f4eSBarry Smith   PCBDDCInitializePackage - This function initializes everything in the `PCBDDC` package. It is called
2887f1580f4eSBarry Smith   from `PCInitializePackage()`.
288843371fb9SStefano Zampini 
288943371fb9SStefano Zampini   Level: developer
289043371fb9SStefano Zampini 
2891562efe2eSBarry Smith .seealso: [](ch_ksp), `PetscInitialize()`, `PCBDDCFinalizePackage()`
289243371fb9SStefano Zampini @*/
PCBDDCInitializePackage(void)2893d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCInitializePackage(void)
2894d71ae5a4SJacob Faibussowitsch {
289543371fb9SStefano Zampini   int i;
289643371fb9SStefano Zampini 
289743371fb9SStefano Zampini   PetscFunctionBegin;
28983ba16761SJacob Faibussowitsch   if (PCBDDCPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS);
289943371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_TRUE;
29009566063dSJacob Faibussowitsch   PetscCall(PetscRegisterFinalize(PCBDDCFinalizePackage));
290143371fb9SStefano Zampini 
290243371fb9SStefano Zampini   /* general events */
29039566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCTopo", PC_CLASSID, &PC_BDDC_Topology[0]));
29049566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCLKSP", PC_CLASSID, &PC_BDDC_LocalSolvers[0]));
29059566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCLWor", PC_CLASSID, &PC_BDDC_LocalWork[0]));
29069566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCorr", PC_CLASSID, &PC_BDDC_CorrectionSetUp[0]));
29079566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCASet", PC_CLASSID, &PC_BDDC_ApproxSetUp[0]));
29089566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCAApp", PC_CLASSID, &PC_BDDC_ApproxApply[0]));
29099566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCSet", PC_CLASSID, &PC_BDDC_CoarseSetUp[0]));
29109566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCKSP", PC_CLASSID, &PC_BDDC_CoarseSolver[0]));
29119566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCAdap", PC_CLASSID, &PC_BDDC_AdaptiveSetUp[0]));
29129566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCScal", PC_CLASSID, &PC_BDDC_Scaling[0]));
29139566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCSchr", PC_CLASSID, &PC_BDDC_Schurs[0]));
29149566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCDirS", PC_CLASSID, &PC_BDDC_Solves[0][0]));
29159566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCNeuS", PC_CLASSID, &PC_BDDC_Solves[0][1]));
29169566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCoaS", PC_CLASSID, &PC_BDDC_Solves[0][2]));
291743371fb9SStefano Zampini   for (i = 1; i < PETSC_PCBDDC_MAXLEVELS; i++) {
291843371fb9SStefano Zampini     char ename[32];
291943371fb9SStefano Zampini 
29209566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCTopo l%02d", i));
29219566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Topology[i]));
29229566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCLKSP l%02d", i));
29239566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_LocalSolvers[i]));
29249566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCLWor l%02d", i));
29259566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_LocalWork[i]));
29269566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCorr l%02d", i));
29279566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CorrectionSetUp[i]));
29289566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCASet l%02d", i));
29299566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_ApproxSetUp[i]));
29309566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCAApp l%02d", i));
29319566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_ApproxApply[i]));
29329566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCSet l%02d", i));
29339566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CoarseSetUp[i]));
29349566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCKSP l%02d", i));
29359566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CoarseSolver[i]));
29369566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCAdap l%02d", i));
29379566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_AdaptiveSetUp[i]));
29389566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCScal l%02d", i));
29399566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Scaling[i]));
29409566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCSchr l%02d", i));
29419566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Schurs[i]));
29429566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCDirS l%02d", i));
29439566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][0]));
29449566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCNeuS l%02d", i));
29459566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][1]));
29469566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCoaS l%02d", i));
29479566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][2]));
294843371fb9SStefano Zampini   }
29493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
295043371fb9SStefano Zampini }
295143371fb9SStefano Zampini 
295243371fb9SStefano Zampini /*@C
2953f1580f4eSBarry Smith   PCBDDCFinalizePackage - This function frees everything from the `PCBDDC` package. It is
2954f1580f4eSBarry Smith   called from `PetscFinalize()` automatically.
295543371fb9SStefano Zampini 
295643371fb9SStefano Zampini   Level: developer
295743371fb9SStefano Zampini 
2958562efe2eSBarry Smith .seealso: [](ch_ksp), `PetscFinalize()`, `PCBDDCInitializePackage()`
295943371fb9SStefano Zampini @*/
PCBDDCFinalizePackage(void)2960d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCFinalizePackage(void)
2961d71ae5a4SJacob Faibussowitsch {
296243371fb9SStefano Zampini   PetscFunctionBegin;
296343371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_FALSE;
29643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
296543371fb9SStefano Zampini }
2966