xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision f4f49eeac7efa77fffa46b7ff95a3ed169f659ed)
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 
3866976f2fSJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_BDDC(PC pc, PetscOptionItems *PetscOptionsObject)
39d71ae5a4SJacob Faibussowitsch {
400c7d97c5SJed Brown   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
41e569e4e1SStefano Zampini   PetscInt nt, i;
420c7d97c5SJed Brown 
430c7d97c5SJed Brown   PetscFunctionBegin;
44d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "BDDC options");
458eeda7d8SStefano Zampini   /* Verbose debugging */
469566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_check_level", "Verbose output for PCBDDC (intended for debug)", "none", pcbddc->dbg_flag, &pcbddc->dbg_flag, NULL));
47a13144ffSStefano Zampini   /* Approximate solvers */
489566063dSJacob 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));
49bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET) {
509566063dSJacob 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));
519566063dSJacob 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));
52bc960bbfSJed Brown   } else {
53bc960bbfSJed Brown     /* This flag is needed/implied by lumping */
54bc960bbfSJed Brown     pcbddc->switch_static = PETSC_TRUE;
55bc960bbfSJed Brown   }
569566063dSJacob 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));
579566063dSJacob 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));
586b78500eSPatrick Sanan   /* Primal space customization */
599566063dSJacob 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));
609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_graph_maxcount", "Maximum number of shared subdomains for a connected component", "none", pcbddc->graphmaxcount, &pcbddc->graphmaxcount, NULL));
619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_corner_selection", "Activates face-based corner selection", "none", pcbddc->corner_selection, &pcbddc->corner_selection, NULL));
629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_vertices", "Use or not corner dofs in coarse space", "none", pcbddc->use_vertices, &pcbddc->use_vertices, NULL));
639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_edges", "Use or not edge constraints in coarse space", "none", pcbddc->use_edges, &pcbddc->use_edges, NULL));
649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_faces", "Use or not face constraints in coarse space", "none", pcbddc->use_faces, &pcbddc->use_faces, NULL));
659566063dSJacob 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));
669566063dSJacob 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));
679566063dSJacob 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));
689566063dSJacob 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));
698eeda7d8SStefano Zampini   /* Change of basis */
709566063dSJacob 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));
719566063dSJacob 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));
72ad540459SPierre Jolivet   if (!pcbddc->use_change_of_basis) pcbddc->use_change_on_faces = PETSC_FALSE;
738eeda7d8SStefano Zampini   /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */
749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_switch_static", "Switch on static condensation ops around the interface preconditioner", "none", pcbddc->switch_static, &pcbddc->switch_static, NULL));
759566063dSJacob 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));
76e569e4e1SStefano Zampini   i = pcbddc->coarsening_ratio;
779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_coarsening_ratio", "Set coarsening ratio used in multilevel coarsening", "PCBDDCSetCoarseningRatio", i, &i, NULL));
789566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetCoarseningRatio(pc, i));
79e569e4e1SStefano Zampini   i = pcbddc->max_levels;
809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_levels", "Set maximum number of levels for multilevel", "PCBDDCSetLevels", i, &i, NULL));
819566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetLevels(pc, i));
829566063dSJacob 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));
839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_coarse_estimates", "Use estimated eigenvalues for coarse problem", "none", pcbddc->use_coarse_estimates, &pcbddc->use_coarse_estimates, NULL));
849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_deluxe_scaling", "Use deluxe scaling for BDDC", "none", pcbddc->use_deluxe_scaling, &pcbddc->use_deluxe_scaling, NULL));
859566063dSJacob 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));
869566063dSJacob 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));
879566063dSJacob 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));
889566063dSJacob 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));
899566063dSJacob 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));
909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_deluxe_singlemat", "Collapse deluxe operators", "none", pcbddc->deluxe_singlemat, &pcbddc->deluxe_singlemat, NULL));
919566063dSJacob 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));
92bd2a564bSStefano Zampini   nt = 2;
939566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRealArray("-pc_bddc_adaptive_threshold", "Thresholds to be used for adaptive selection of constraints", "none", pcbddc->adaptive_threshold, &nt, NULL));
94bd2a564bSStefano Zampini   if (nt == 1) pcbddc->adaptive_threshold[1] = pcbddc->adaptive_threshold[0];
959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_adaptive_nmin", "Minimum number of constraints per connected components", "none", pcbddc->adaptive_nmin, &pcbddc->adaptive_nmin, NULL));
969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_adaptive_nmax", "Maximum number of constraints per connected components", "none", pcbddc->adaptive_nmax, &pcbddc->adaptive_nmax, NULL));
979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_symmetric", "Symmetric computation of primal basis functions", "none", pcbddc->symmetric_primal, &pcbddc->symmetric_primal, NULL));
989566063dSJacob 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));
999566063dSJacob 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));
1009566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_benign_change", "Compute the pressure change of basis explicitly", "none", pcbddc->benign_change_explicit, &pcbddc->benign_change_explicit, NULL));
1019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_benign_compute_correction", "Compute the benign correction during PreSolve", "none", pcbddc->benign_compute_correction, &pcbddc->benign_compute_correction, NULL));
1029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_nonetflux", "Automatic computation of no-net-flux quadrature weights", "none", pcbddc->compute_nonetflux, &pcbddc->compute_nonetflux, NULL));
1039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_detect_disconnected", "Detects disconnected subdomains", "none", pcbddc->detect_disconnected, &pcbddc->detect_disconnected, NULL));
1049566063dSJacob 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));
1059566063dSJacob 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));
106d0609cedSBarry Smith   PetscOptionsHeadEnd();
1073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1080c7d97c5SJed Brown }
1096b78500eSPatrick Sanan 
110d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_BDDC(PC pc, PetscViewer viewer)
111d71ae5a4SJacob Faibussowitsch {
1126b78500eSPatrick Sanan   PC_BDDC     *pcbddc = (PC_BDDC *)pc->data;
113e9627c49SStefano Zampini   PC_IS       *pcis   = (PC_IS *)pc->data;
11471783a16SStefano Zampini   PetscBool    isascii;
115e9627c49SStefano Zampini   PetscSubcomm subcomm;
116e9627c49SStefano Zampini   PetscViewer  subviewer;
1176b78500eSPatrick Sanan 
1186b78500eSPatrick Sanan   PetscFunctionBegin;
1199566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1206b78500eSPatrick Sanan   /* ASCII viewer */
1216b78500eSPatrick Sanan   if (isascii) {
1224b2aedd3SStefano Zampini     PetscMPIInt color, rank, size;
123fbad9177SStefano Zampini     PetscInt64  loc[7], gsum[6], gmax[6], gmin[6], totbenign;
124e9627c49SStefano Zampini     PetscScalar interface_size;
125e9627c49SStefano Zampini     PetscReal   ratio1 = 0., ratio2 = 0.;
126e9627c49SStefano Zampini     Vec         counter;
1276b78500eSPatrick Sanan 
12848a46eb9SPierre Jolivet     if (!pc->setupcalled) PetscCall(PetscViewerASCIIPrintf(viewer, "  Partial information available: preconditioner has not been setup yet\n"));
12963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use verbose output: %" PetscInt_FMT "\n", pcbddc->dbg_flag));
1309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use user-defined CSR: %d\n", !!pcbddc->mat_graph->nvtxs_csr));
1319566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use local mat graph: %d\n", pcbddc->use_local_adj && !pcbddc->mat_graph->nvtxs_csr));
132e9627c49SStefano Zampini     if (pcbddc->mat_graph->twodim) {
1339566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Connectivity graph topological dimension: 2\n"));
134e9627c49SStefano Zampini     } else {
1359566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  Connectivity graph topological dimension: 3\n"));
136e9627c49SStefano Zampini     }
13748a46eb9SPierre Jolivet     if (pcbddc->graphmaxcount != PETSC_MAX_INT) PetscCall(PetscViewerASCIIPrintf(viewer, "  Graph max count: %" PetscInt_FMT "\n", pcbddc->graphmaxcount));
1389566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Corner selection: %d (selected %d)\n", pcbddc->corner_selection, pcbddc->corner_selected));
13963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use vertices: %d (vertex size %" PetscInt_FMT ")\n", pcbddc->use_vertices, pcbddc->vertex_size));
1409566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use edges: %d\n", pcbddc->use_edges));
1419566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use faces: %d\n", pcbddc->use_faces));
1429566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use true near null space: %d\n", pcbddc->use_nnsp_true));
1439566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use QR for single constraints on cc: %d\n", pcbddc->use_qr_single));
1449566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use change of basis on local edge nodes: %d\n", pcbddc->use_change_of_basis));
1459566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use change of basis on local face nodes: %d\n", pcbddc->use_change_on_faces));
1469566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  User defined change of basis matrix: %d\n", !!pcbddc->user_ChangeOfBasisMatrix));
1479566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Has change of basis matrix: %d\n", !!pcbddc->ChangeOfBasisMatrix));
1489566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Eliminate dirichlet boundary dofs: %d\n", pcbddc->eliminate_dirdofs));
1499566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Switch on static condensation ops around the interface preconditioner: %d\n", pcbddc->switch_static));
1509566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use exact dirichlet trick: %d\n", pcbddc->use_exact_dirichlet_trick));
1519566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Interface extension: %s\n", PCBDDCInterfaceExtTypes[pcbddc->interface_extension]));
15263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Multilevel max levels: %" PetscInt_FMT "\n", pcbddc->max_levels));
15363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Multilevel coarsening ratio: %" PetscInt_FMT "\n", pcbddc->coarsening_ratio));
1549566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use estimated eigs for coarse problem: %d\n", pcbddc->use_coarse_estimates));
1559566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use deluxe scaling: %d\n", pcbddc->use_deluxe_scaling));
1569566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use deluxe zerorows: %d\n", pcbddc->deluxe_zerorows));
1579566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use deluxe singlemat: %d\n", pcbddc->deluxe_singlemat));
1589566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Rebuild interface graph for Schur principal minors: %d\n", pcbddc->sub_schurs_rebuild));
15963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of dofs' layers for the computation of principal minors: %" PetscInt_FMT "\n", pcbddc->sub_schurs_layers));
1609566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Use user CSR graph to compute successive layers: %d\n", pcbddc->sub_schurs_use_useradj));
161bd2a564bSStefano Zampini     if (pcbddc->adaptive_threshold[1] != pcbddc->adaptive_threshold[0]) {
16263a3b9bcSJacob 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]));
163bd2a564bSStefano Zampini     } else {
16463a3b9bcSJacob 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]));
165bd2a564bSStefano Zampini     }
16663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Min constraints / connected component: %" PetscInt_FMT "\n", pcbddc->adaptive_nmin));
16763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Max constraints / connected component: %" PetscInt_FMT "\n", pcbddc->adaptive_nmax));
1689566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Invert exact Schur complement for adaptive selection: %d\n", pcbddc->sub_schurs_exact_schur));
1699566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Symmetric computation of primal basis functions: %d\n", pcbddc->symmetric_primal));
17063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Num. Procs. to map coarse adjacency list: %" PetscInt_FMT "\n", pcbddc->coarse_adj_red));
17163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Coarse eqs per proc (significant at the coarsest level): %" PetscInt_FMT "\n", pcbddc->coarse_eqs_per_proc));
1729566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Detect disconnected: %d (filter %d)\n", pcbddc->detect_disconnected, pcbddc->detect_disconnected_filter));
1739566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Benign subspace trick: %d (change explicit %d)\n", pcbddc->benign_saddle_point, pcbddc->benign_change_explicit));
1749566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Benign subspace trick is active: %d\n", pcbddc->benign_have_null));
1759566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Algebraic computation of no-net-flux: %d\n", pcbddc->compute_nonetflux));
1763ba16761SJacob Faibussowitsch     if (!pc->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
1776b78500eSPatrick Sanan 
178fbad9177SStefano Zampini     /* compute interface size */
1799566063dSJacob Faibussowitsch     PetscCall(VecSet(pcis->vec1_B, 1.0));
1809566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(pc->pmat, &counter, NULL));
1819566063dSJacob Faibussowitsch     PetscCall(VecSet(counter, 0.0));
1829566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, counter, INSERT_VALUES, SCATTER_REVERSE));
1839566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, counter, INSERT_VALUES, SCATTER_REVERSE));
1849566063dSJacob Faibussowitsch     PetscCall(VecSum(counter, &interface_size));
1859566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&counter));
186fbad9177SStefano Zampini 
187fbad9177SStefano Zampini     /* compute some statistics on the domain decomposition */
188e9627c49SStefano Zampini     gsum[0] = 1;
189fbad9177SStefano Zampini     gsum[1] = gsum[2] = gsum[3] = gsum[4] = gsum[5] = 0;
190e9627c49SStefano Zampini     loc[0]                                          = !!pcis->n;
191e9627c49SStefano Zampini     loc[1]                                          = pcis->n - pcis->n_B;
192e9627c49SStefano Zampini     loc[2]                                          = pcis->n_B;
193e9627c49SStefano Zampini     loc[3]                                          = pcbddc->local_primal_size;
194345ecf6cSStefano Zampini     loc[4]                                          = pcis->n;
195fbad9177SStefano Zampini     loc[5]                                          = pcbddc->n_local_subs > 0 ? pcbddc->n_local_subs : (pcis->n ? 1 : 0);
196fbad9177SStefano Zampini     loc[6]                                          = pcbddc->benign_n;
1979566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(loc, gsum, 6, MPIU_INT64, MPI_SUM, 0, PetscObjectComm((PetscObject)pc)));
198fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = -1;
1999566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(loc, gmax, 6, MPIU_INT64, MPI_MAX, 0, PetscObjectComm((PetscObject)pc)));
200fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = PETSC_MAX_INT;
2019566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(loc, gmin, 6, MPIU_INT64, MPI_MIN, 0, PetscObjectComm((PetscObject)pc)));
2029566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&loc[6], &totbenign, 1, MPIU_INT64, MPI_SUM, 0, PetscObjectComm((PetscObject)pc)));
203e9627c49SStefano Zampini     if (pcbddc->coarse_size) {
204e9627c49SStefano Zampini       ratio1 = pc->pmat->rmap->N / (1. * pcbddc->coarse_size);
205e9627c49SStefano Zampini       ratio2 = PetscRealPart(interface_size) / pcbddc->coarse_size;
206e9627c49SStefano Zampini     }
20763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "********************************** STATISTICS AT LEVEL %" PetscInt_FMT " **********************************\n", pcbddc->current_level));
20863a3b9bcSJacob 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));
20963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Coarsening ratios: all/coarse %" PetscInt_FMT " interface/coarse %" PetscInt_FMT "\n", (PetscInt)ratio1, (PetscInt)ratio2));
21063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Active processes : %" PetscInt_FMT "\n", (PetscInt)gsum[0]));
21163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Total subdomains : %" PetscInt_FMT "\n", (PetscInt)gsum[5]));
21248a46eb9SPierre Jolivet     if (pcbddc->benign_have_null) PetscCall(PetscViewerASCIIPrintf(viewer, "  Benign subs      : %" PetscInt_FMT "\n", (PetscInt)totbenign));
2139566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Dofs type        :\tMIN\tMAX\tMEAN\n"));
21463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Interior  dofs   :\t%" PetscInt_FMT "\t%" PetscInt_FMT "\t%" PetscInt_FMT "\n", (PetscInt)gmin[1], (PetscInt)gmax[1], (PetscInt)(gsum[1] / gsum[0])));
21563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Interface dofs   :\t%" PetscInt_FMT "\t%" PetscInt_FMT "\t%" PetscInt_FMT "\n", (PetscInt)gmin[2], (PetscInt)gmax[2], (PetscInt)(gsum[2] / gsum[0])));
21663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Primal    dofs   :\t%" PetscInt_FMT "\t%" PetscInt_FMT "\t%" PetscInt_FMT "\n", (PetscInt)gmin[3], (PetscInt)gmax[3], (PetscInt)(gsum[3] / gsum[0])));
21763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Local     dofs   :\t%" PetscInt_FMT "\t%" PetscInt_FMT "\t%" PetscInt_FMT "\n", (PetscInt)gmin[4], (PetscInt)gmax[4], (PetscInt)(gsum[4] / gsum[0])));
21863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Local     subs   :\t%" PetscInt_FMT "\t%" PetscInt_FMT "\n", (PetscInt)gmin[5], (PetscInt)gmax[5]));
2199566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
22015579a77SStefano Zampini 
2219566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc), &rank));
22215579a77SStefano Zampini 
22315579a77SStefano Zampini     /* local solvers */
2249566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetSubViewer(viewer, PetscObjectComm((PetscObject)pcbddc->ksp_D), &subviewer));
225dd400576SPatrick Sanan     if (rank == 0) {
2269566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(subviewer, "--- Interior solver (rank 0)\n"));
2279566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(subviewer));
2289566063dSJacob Faibussowitsch       PetscCall(KSPView(pcbddc->ksp_D, subviewer));
2299566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(subviewer));
2309566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(subviewer, "--- Correction solver (rank 0)\n"));
2319566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(subviewer));
2329566063dSJacob Faibussowitsch       PetscCall(KSPView(pcbddc->ksp_R, subviewer));
2339566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(subviewer));
2349566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(subviewer));
23515579a77SStefano Zampini     }
2369566063dSJacob Faibussowitsch     PetscCall(PetscViewerRestoreSubViewer(viewer, PetscObjectComm((PetscObject)pcbddc->ksp_D), &subviewer));
237fbad9177SStefano Zampini     /* the coarse problem can be handled by a different communicator */
238e9627c49SStefano Zampini     if (pcbddc->coarse_ksp) color = 1;
239e9627c49SStefano Zampini     else color = 0;
2409566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
2419566063dSJacob Faibussowitsch     PetscCall(PetscSubcommCreate(PetscObjectComm((PetscObject)pc), &subcomm));
2429566063dSJacob Faibussowitsch     PetscCall(PetscSubcommSetNumber(subcomm, PetscMin(size, 2)));
2439566063dSJacob Faibussowitsch     PetscCall(PetscSubcommSetTypeGeneral(subcomm, color, rank));
2449566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetSubViewer(viewer, PetscSubcommChild(subcomm), &subviewer));
245e9627c49SStefano Zampini     if (color == 1) {
2469566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(subviewer, "--- Coarse solver\n"));
2479566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(subviewer));
2489566063dSJacob Faibussowitsch       PetscCall(KSPView(pcbddc->coarse_ksp, subviewer));
2499566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(subviewer));
2509566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(subviewer));
251e9627c49SStefano Zampini     }
2529566063dSJacob Faibussowitsch     PetscCall(PetscViewerRestoreSubViewer(viewer, PetscSubcommChild(subcomm), &subviewer));
2539566063dSJacob Faibussowitsch     PetscCall(PetscSubcommDestroy(&subcomm));
2549566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
255e9627c49SStefano Zampini   }
2563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2576b78500eSPatrick Sanan }
258a13144ffSStefano Zampini 
259d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDiscreteGradient_BDDC(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
260d71ae5a4SJacob Faibussowitsch {
261a13144ffSStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
262a13144ffSStefano Zampini 
263a13144ffSStefano Zampini   PetscFunctionBegin;
2649566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)G));
2659566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->discretegradient));
266a13144ffSStefano Zampini   pcbddc->discretegradient = G;
267a13144ffSStefano Zampini   pcbddc->nedorder         = order > 0 ? order : -order;
268495a2a07SStefano Zampini   pcbddc->nedfield         = field;
2691e0482f5SStefano Zampini   pcbddc->nedglobal        = global;
2701e0482f5SStefano Zampini   pcbddc->conforming       = conforming;
2713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
272a13144ffSStefano Zampini }
273a13144ffSStefano Zampini 
274a13144ffSStefano Zampini /*@
27598ad52f2SBarry Smith   PCBDDCSetDiscreteGradient - Sets the discrete gradient to be used by the `PCBDDC` preconditioner
276a13144ffSStefano Zampini 
277c3339decSBarry Smith   Collective
278a13144ffSStefano Zampini 
279a13144ffSStefano Zampini   Input Parameters:
280a13144ffSStefano Zampini + pc         - the preconditioning context
281f1580f4eSBarry Smith . G          - the discrete gradient matrix (in `MATAIJ` format)
282a13144ffSStefano Zampini . order      - the order of the Nedelec space (1 for the lowest order)
283495a2a07SStefano Zampini . field      - the field id of the Nedelec dofs (not used if the fields have not been specified)
28498ad52f2SBarry Smith . global     - the type of global ordering for the rows of `G`
285a13144ffSStefano Zampini - conforming - whether the mesh is conforming or not
286a13144ffSStefano Zampini 
287a13144ffSStefano Zampini   Level: advanced
288a13144ffSStefano Zampini 
289f1580f4eSBarry Smith   Note:
29020f4b53cSBarry Smith   The discrete gradient matrix `G` is used to analyze the subdomain edges, and it should not contain any zero entry.
291495a2a07SStefano Zampini   For variable order spaces, the order should be set to zero.
29298ad52f2SBarry Smith   If `global` is `PETSC_TRUE`, the rows of `G` should be given in global ordering for the whole dofs;
29398ad52f2SBarry Smith   if `PETSC_FALSE`, the ordering should be global for the Nedelec field.
2941e0482f5SStefano 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
2951e0482f5SStefano Zampini   and geid the one for the Nedelec field.
296a13144ffSStefano Zampini 
297562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDofsSplitting()`, `PCBDDCSetDofsSplittingLocal()`, `MATAIJ`, `PCBDDCSetDivergenceMat()`
298a13144ffSStefano Zampini @*/
299d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDiscreteGradient(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
300d71ae5a4SJacob Faibussowitsch {
301a13144ffSStefano Zampini   PetscFunctionBegin;
302a13144ffSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
303a13144ffSStefano Zampini   PetscValidHeaderSpecific(G, MAT_CLASSID, 2);
304a13144ffSStefano Zampini   PetscValidLogicalCollectiveInt(pc, order, 3);
3051e0482f5SStefano Zampini   PetscValidLogicalCollectiveInt(pc, field, 4);
3061e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc, global, 5);
3071e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc, conforming, 6);
3081e0482f5SStefano Zampini   PetscCheckSameComm(pc, 1, G, 2);
309cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDiscreteGradient_C", (PC, Mat, PetscInt, PetscInt, PetscBool, PetscBool), (pc, G, order, field, global, conforming));
3103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
311a13144ffSStefano Zampini }
312a13144ffSStefano Zampini 
313d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDivergenceMat_BDDC(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
314d71ae5a4SJacob Faibussowitsch {
315a198735bSStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
3166b78500eSPatrick Sanan 
317a198735bSStefano Zampini   PetscFunctionBegin;
3189566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)divudotp));
3199566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->divudotp));
320a198735bSStefano Zampini   pcbddc->divudotp          = divudotp;
3218ae0ca82SStefano Zampini   pcbddc->divudotp_trans    = trans;
322a198735bSStefano Zampini   pcbddc->compute_nonetflux = PETSC_TRUE;
323a198735bSStefano Zampini   if (vl2l) {
3249566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)vl2l));
3259566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&pcbddc->divudotp_vl2l));
326a198735bSStefano Zampini     pcbddc->divudotp_vl2l = vl2l;
327a198735bSStefano Zampini   }
3283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
329a198735bSStefano Zampini }
3303d996552SStefano Zampini 
331a198735bSStefano Zampini /*@
33298ad52f2SBarry Smith   PCBDDCSetDivergenceMat - Sets the linear operator representing \int_\Omega \div {\bf u} \cdot p dx for the `PCBDDC` preconditioner
333a198735bSStefano Zampini 
334c3339decSBarry Smith   Collective
335a198735bSStefano Zampini 
336a198735bSStefano Zampini   Input Parameters:
337a198735bSStefano Zampini + pc       - the preconditioning context
338f1580f4eSBarry Smith . divudotp - the matrix (must be of type `MATIS`)
33998ad52f2SBarry Smith . trans    - if `PETSC_FALSE` (resp. `PETSC_TRUE`), then pressures are in the test (trial) space and velocities are in the trial (test) space.
34098ad52f2SBarry Smith - vl2l     - optional index set describing the local (wrt the local matrix in `divudotp`) to local (wrt the local matrix
341f1580f4eSBarry Smith    in the preconditioning matrix) map for the velocities
342a198735bSStefano Zampini 
343a198735bSStefano Zampini   Level: advanced
344a198735bSStefano Zampini 
34595452b02SPatrick Sanan   Notes:
34695452b02SPatrick Sanan   This auxiliary matrix is used to compute quadrature weights representing the net-flux across subdomain boundaries
347f1580f4eSBarry Smith 
34898ad52f2SBarry Smith   If `vl2l` is `NULL`, the local ordering for velocities in `divudotp` should match that of the preconditioning matrix
349a198735bSStefano Zampini 
350562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDiscreteGradient()`
351a198735bSStefano Zampini @*/
352d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDivergenceMat(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
353d71ae5a4SJacob Faibussowitsch {
354a198735bSStefano Zampini   PetscBool ismatis;
355a198735bSStefano Zampini 
356a198735bSStefano Zampini   PetscFunctionBegin;
357a198735bSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
358a198735bSStefano Zampini   PetscValidHeaderSpecific(divudotp, MAT_CLASSID, 2);
359a198735bSStefano Zampini   PetscCheckSameComm(pc, 1, divudotp, 2);
3608ae0ca82SStefano Zampini   PetscValidLogicalCollectiveBool(pc, trans, 3);
3611b24a7afSStefano Zampini   if (vl2l) PetscValidHeaderSpecific(vl2l, IS_CLASSID, 4);
3629566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)divudotp, MATIS, &ismatis));
36328b400f6SJacob Faibussowitsch   PetscCheck(ismatis, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Divergence matrix needs to be of type MATIS");
364cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDivergenceMat_C", (PC, Mat, PetscBool, IS), (pc, divudotp, trans, vl2l));
3653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
366a198735bSStefano Zampini }
3672d505d7fSStefano Zampini 
368d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change, PetscBool interior)
369d71ae5a4SJacob Faibussowitsch {
370b9b85e73SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
371b9b85e73SStefano Zampini 
372b9b85e73SStefano Zampini   PetscFunctionBegin;
3739566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)change));
3749566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->user_ChangeOfBasisMatrix));
375b9b85e73SStefano Zampini   pcbddc->user_ChangeOfBasisMatrix = change;
3761dd7afcfSStefano Zampini   pcbddc->change_interior          = interior;
3773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
378b9b85e73SStefano Zampini }
37932fe681dSStefano Zampini 
380b9b85e73SStefano Zampini /*@
381906d46d4SStefano Zampini   PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs
382b9b85e73SStefano Zampini 
383c3339decSBarry Smith   Collective
384b9b85e73SStefano Zampini 
385b9b85e73SStefano Zampini   Input Parameters:
386b9b85e73SStefano Zampini + pc       - the preconditioning context
3871dd7afcfSStefano Zampini . change   - the change of basis matrix
3881dd7afcfSStefano Zampini - interior - whether or not the change of basis modifies interior dofs
389b9b85e73SStefano Zampini 
390b9b85e73SStefano Zampini   Level: intermediate
391b9b85e73SStefano Zampini 
392562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`
393b9b85e73SStefano Zampini @*/
394d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change, PetscBool interior)
395d71ae5a4SJacob Faibussowitsch {
396b9b85e73SStefano Zampini   PetscFunctionBegin;
397b9b85e73SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
398b9b85e73SStefano Zampini   PetscValidHeaderSpecific(change, MAT_CLASSID, 2);
399906d46d4SStefano Zampini   PetscCheckSameComm(pc, 1, change, 2);
400906d46d4SStefano Zampini   if (pc->mat) {
401906d46d4SStefano Zampini     PetscInt rows_c, cols_c, rows, cols;
4029566063dSJacob Faibussowitsch     PetscCall(MatGetSize(pc->mat, &rows, &cols));
4039566063dSJacob Faibussowitsch     PetscCall(MatGetSize(change, &rows_c, &cols_c));
40463a3b9bcSJacob 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);
40563a3b9bcSJacob 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);
4069566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(pc->mat, &rows, &cols));
4079566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(change, &rows_c, &cols_c));
40863a3b9bcSJacob 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);
40963a3b9bcSJacob 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);
410906d46d4SStefano Zampini   }
411cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetChangeOfBasisMat_C", (PC, Mat, PetscBool), (pc, change, interior));
4123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
413b9b85e73SStefano Zampini }
4142d505d7fSStefano Zampini 
415d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetPrimalVerticesIS_BDDC(PC pc, IS PrimalVertices)
416d71ae5a4SJacob Faibussowitsch {
41730368db7SStefano Zampini   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
41856282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
41930368db7SStefano Zampini 
42030368db7SStefano Zampini   PetscFunctionBegin;
4219566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)PrimalVertices));
42248a46eb9SPierre Jolivet   if (pcbddc->user_primal_vertices) PetscCall(ISEqual(PrimalVertices, pcbddc->user_primal_vertices, &isequal));
4239566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices));
4249566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local));
42530368db7SStefano Zampini   pcbddc->user_primal_vertices = PrimalVertices;
42656282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
4273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42830368db7SStefano Zampini }
429ab8c8b98SStefano Zampini 
43030368db7SStefano Zampini /*@
431f1580f4eSBarry Smith   PCBDDCSetPrimalVerticesIS - Set additional user defined primal vertices in `PCBDDC`
43230368db7SStefano Zampini 
43330368db7SStefano Zampini   Collective
43430368db7SStefano Zampini 
43530368db7SStefano Zampini   Input Parameters:
43630368db7SStefano Zampini + pc             - the preconditioning context
43730368db7SStefano Zampini - PrimalVertices - index set of primal vertices in global numbering (can be empty)
43830368db7SStefano Zampini 
43930368db7SStefano Zampini   Level: intermediate
44030368db7SStefano Zampini 
441f1580f4eSBarry Smith   Note:
44230368db7SStefano Zampini   Any process can list any global node
44330368db7SStefano Zampini 
444562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`, `PCBDDCGetPrimalVerticesLocalIS()`
44530368db7SStefano Zampini @*/
446d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetPrimalVerticesIS(PC pc, IS PrimalVertices)
447d71ae5a4SJacob Faibussowitsch {
44830368db7SStefano Zampini   PetscFunctionBegin;
44930368db7SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
45030368db7SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices, IS_CLASSID, 2);
45130368db7SStefano Zampini   PetscCheckSameComm(pc, 1, PrimalVertices, 2);
452cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetPrimalVerticesIS_C", (PC, IS), (pc, PrimalVertices));
4533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
45430368db7SStefano Zampini }
4552d505d7fSStefano Zampini 
456d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetPrimalVerticesIS_BDDC(PC pc, IS *is)
457d71ae5a4SJacob Faibussowitsch {
4583100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
4593100ebe3SStefano Zampini 
4603100ebe3SStefano Zampini   PetscFunctionBegin;
4613100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices;
4623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4633100ebe3SStefano Zampini }
4643100ebe3SStefano Zampini 
4653100ebe3SStefano Zampini /*@
466f1580f4eSBarry Smith   PCBDDCGetPrimalVerticesIS - Get user defined primal vertices set with `PCBDDCSetPrimalVerticesIS()`
4673100ebe3SStefano Zampini 
4683100ebe3SStefano Zampini   Collective
4693100ebe3SStefano Zampini 
470f1580f4eSBarry Smith   Input Parameter:
4713100ebe3SStefano Zampini . pc - the preconditioning context
4723100ebe3SStefano Zampini 
473f1580f4eSBarry Smith   Output Parameter:
47420f4b53cSBarry Smith . is - index set of primal vertices in global numbering (`NULL` if not set)
4753100ebe3SStefano Zampini 
4763100ebe3SStefano Zampini   Level: intermediate
4773100ebe3SStefano Zampini 
478562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`, `PCBDDCGetPrimalVerticesLocalIS()`
4793100ebe3SStefano Zampini @*/
480d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetPrimalVerticesIS(PC pc, IS *is)
481d71ae5a4SJacob Faibussowitsch {
4823100ebe3SStefano Zampini   PetscFunctionBegin;
4833100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
4844f572ea9SToby Isaac   PetscAssertPointer(is, 2);
485cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetPrimalVerticesIS_C", (PC, IS *), (pc, is));
4863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4873100ebe3SStefano Zampini }
4883100ebe3SStefano Zampini 
489d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
490d71ae5a4SJacob Faibussowitsch {
491674ae819SStefano Zampini   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
49256282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
4931e6b0712SBarry Smith 
494674ae819SStefano Zampini   PetscFunctionBegin;
4959566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)PrimalVertices));
49648a46eb9SPierre Jolivet   if (pcbddc->user_primal_vertices_local) PetscCall(ISEqual(PrimalVertices, pcbddc->user_primal_vertices_local, &isequal));
4979566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices));
4989566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local));
49930368db7SStefano Zampini   pcbddc->user_primal_vertices_local = PrimalVertices;
50056282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
5013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
502674ae819SStefano Zampini }
5033100ebe3SStefano Zampini 
504674ae819SStefano Zampini /*@
505f1580f4eSBarry Smith   PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in `PCBDDC`
506674ae819SStefano Zampini 
50717eb1463SStefano Zampini   Collective
508674ae819SStefano Zampini 
509674ae819SStefano Zampini   Input Parameters:
510674ae819SStefano Zampini + pc             - the preconditioning context
51117eb1463SStefano Zampini - PrimalVertices - index set of primal vertices in local numbering (can be empty)
512674ae819SStefano Zampini 
513674ae819SStefano Zampini   Level: intermediate
514674ae819SStefano Zampini 
515562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesLocalIS()`
516674ae819SStefano Zampini @*/
517d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
518d71ae5a4SJacob Faibussowitsch {
519674ae819SStefano Zampini   PetscFunctionBegin;
520674ae819SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
521674ae819SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices, IS_CLASSID, 2);
52217eb1463SStefano Zampini   PetscCheckSameComm(pc, 1, PrimalVertices, 2);
523cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetPrimalVerticesLocalIS_C", (PC, IS), (pc, PrimalVertices));
5243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
525674ae819SStefano Zampini }
5262d505d7fSStefano Zampini 
527d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetPrimalVerticesLocalIS_BDDC(PC pc, IS *is)
528d71ae5a4SJacob Faibussowitsch {
5293100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
5303100ebe3SStefano Zampini 
5313100ebe3SStefano Zampini   PetscFunctionBegin;
5323100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices_local;
5333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5343100ebe3SStefano Zampini }
5353100ebe3SStefano Zampini 
5363100ebe3SStefano Zampini /*@
537f1580f4eSBarry Smith   PCBDDCGetPrimalVerticesLocalIS - Get user defined primal vertices set with `PCBDDCSetPrimalVerticesLocalIS()`
5383100ebe3SStefano Zampini 
5393100ebe3SStefano Zampini   Collective
5403100ebe3SStefano Zampini 
541f1580f4eSBarry Smith   Input Parameter:
5423100ebe3SStefano Zampini . pc - the preconditioning context
5433100ebe3SStefano Zampini 
544f1580f4eSBarry Smith   Output Parameter:
54520f4b53cSBarry Smith . is - index set of primal vertices in local numbering (`NULL` if not set)
5463100ebe3SStefano Zampini 
5473100ebe3SStefano Zampini   Level: intermediate
5483100ebe3SStefano Zampini 
549562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`
5503100ebe3SStefano Zampini @*/
551d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetPrimalVerticesLocalIS(PC pc, IS *is)
552d71ae5a4SJacob Faibussowitsch {
5533100ebe3SStefano Zampini   PetscFunctionBegin;
5543100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
5554f572ea9SToby Isaac   PetscAssertPointer(is, 2);
556cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetPrimalVerticesLocalIS_C", (PC, IS *), (pc, is));
5573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5583100ebe3SStefano Zampini }
5593100ebe3SStefano Zampini 
560d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc, PetscInt k)
561d71ae5a4SJacob Faibussowitsch {
5624fad6a16SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
5634fad6a16SStefano Zampini 
5644fad6a16SStefano Zampini   PetscFunctionBegin;
5654fad6a16SStefano Zampini   pcbddc->coarsening_ratio = k;
5663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5674fad6a16SStefano Zampini }
5681e6b0712SBarry Smith 
5694fad6a16SStefano Zampini /*@
57098ad52f2SBarry Smith   PCBDDCSetCoarseningRatio - Set coarsening ratio used in the multi-level version of `PCBDDC`
5714fad6a16SStefano Zampini 
57220f4b53cSBarry Smith   Logically Collective
5734fad6a16SStefano Zampini 
5744fad6a16SStefano Zampini   Input Parameters:
5754fad6a16SStefano Zampini + pc - the preconditioning context
57628509bceSStefano Zampini - k  - coarsening ratio (H/h at the coarser level)
5774fad6a16SStefano Zampini 
578f1580f4eSBarry Smith   Options Database Key:
57998ad52f2SBarry Smith . -pc_bddc_coarsening_ratio <int> - Set the coarsening ratio used in multi-level coarsening
5804fad6a16SStefano Zampini 
5814fad6a16SStefano Zampini   Level: intermediate
5824fad6a16SStefano Zampini 
583f1580f4eSBarry Smith   Note:
58420f4b53cSBarry Smith   Approximately `k` subdomains at the finer level will be aggregated into a single subdomain at the coarser level
5854fad6a16SStefano Zampini 
586562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetLevels()`
5874fad6a16SStefano Zampini @*/
588d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetCoarseningRatio(PC pc, PetscInt k)
589d71ae5a4SJacob Faibussowitsch {
5904fad6a16SStefano Zampini   PetscFunctionBegin;
5914fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
5922b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc, k, 2);
593cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetCoarseningRatio_C", (PC, PetscInt), (pc, k));
5943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5954fad6a16SStefano Zampini }
5962b510759SStefano Zampini 
597b8ffe317SStefano Zampini /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */
598d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc, PetscBool flg)
599d71ae5a4SJacob Faibussowitsch {
600b8ffe317SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
601b8ffe317SStefano Zampini 
602b8ffe317SStefano Zampini   PetscFunctionBegin;
60385c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = flg;
6043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
605b8ffe317SStefano Zampini }
606b8ffe317SStefano Zampini 
607d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc, PetscBool flg)
608d71ae5a4SJacob Faibussowitsch {
6092b510759SStefano Zampini   PetscFunctionBegin;
6102b510759SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
611b8ffe317SStefano Zampini   PetscValidLogicalCollectiveBool(pc, flg, 2);
612cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetUseExactDirichlet_C", (PC, PetscBool), (pc, flg));
6133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6142b510759SStefano Zampini }
6151e6b0712SBarry Smith 
616d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc, PetscInt level)
617d71ae5a4SJacob Faibussowitsch {
6184fad6a16SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
6194fad6a16SStefano Zampini 
6204fad6a16SStefano Zampini   PetscFunctionBegin;
6212b510759SStefano Zampini   pcbddc->current_level = level;
6223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6234fad6a16SStefano Zampini }
6241e6b0712SBarry Smith 
625d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetLevel(PC pc, PetscInt level)
626d71ae5a4SJacob Faibussowitsch {
627b8ffe317SStefano Zampini   PetscFunctionBegin;
628b8ffe317SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
629b8ffe317SStefano Zampini   PetscValidLogicalCollectiveInt(pc, level, 2);
630cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetLevel_C", (PC, PetscInt), (pc, level));
6313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
632b8ffe317SStefano Zampini }
633b8ffe317SStefano Zampini 
634d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc, PetscInt levels)
635d71ae5a4SJacob Faibussowitsch {
6362b510759SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
6372b510759SStefano Zampini 
6382b510759SStefano Zampini   PetscFunctionBegin;
6397827d75bSBarry Smith   PetscCheck(levels < PETSC_PCBDDC_MAXLEVELS, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Maximum number of additional levels for BDDC is %d", PETSC_PCBDDC_MAXLEVELS - 1);
6402b510759SStefano Zampini   pcbddc->max_levels = levels;
6413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6422b510759SStefano Zampini }
6432b510759SStefano Zampini 
6444fad6a16SStefano Zampini /*@
645f1580f4eSBarry Smith   PCBDDCSetLevels - Sets the maximum number of additional levels allowed for multilevel `PCBDDC`
6464fad6a16SStefano Zampini 
64720f4b53cSBarry Smith   Logically Collective
6484fad6a16SStefano Zampini 
6494fad6a16SStefano Zampini   Input Parameters:
6504fad6a16SStefano Zampini + pc     - the preconditioning context
65137ebbdf7SStefano Zampini - levels - the maximum number of levels
6524fad6a16SStefano Zampini 
653f1580f4eSBarry Smith   Options Database Key:
65467b8a455SSatish Balay . -pc_bddc_levels <int> - Set maximum number of levels for multilevel
6554fad6a16SStefano Zampini 
6564fad6a16SStefano Zampini   Level: intermediate
6574fad6a16SStefano Zampini 
658f1580f4eSBarry Smith   Note:
65998ad52f2SBarry Smith   The default value is 0, that gives the classical two-levels BDDC algorithm
6604fad6a16SStefano Zampini 
661562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetCoarseningRatio()`
6624fad6a16SStefano Zampini @*/
663d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetLevels(PC pc, PetscInt levels)
664d71ae5a4SJacob Faibussowitsch {
6654fad6a16SStefano Zampini   PetscFunctionBegin;
6664fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
6672b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc, levels, 2);
668cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetLevels_C", (PC, PetscInt), (pc, levels));
6693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6704fad6a16SStefano Zampini }
6711e6b0712SBarry Smith 
672d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc, IS DirichletBoundaries)
673d71ae5a4SJacob Faibussowitsch {
6743b03a366Sstefano_zampini   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
67556282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
6763b03a366Sstefano_zampini 
6773b03a366Sstefano_zampini   PetscFunctionBegin;
6789566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)DirichletBoundaries));
67948a46eb9SPierre Jolivet   if (pcbddc->DirichletBoundaries) PetscCall(ISEqual(DirichletBoundaries, pcbddc->DirichletBoundaries, &isequal));
680a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
6819566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal));
6829566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundaries));
68336e030ebSStefano Zampini   pcbddc->DirichletBoundaries = DirichletBoundaries;
68456282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
6853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6863b03a366Sstefano_zampini }
6871e6b0712SBarry Smith 
6883b03a366Sstefano_zampini /*@
68998ad52f2SBarry Smith   PCBDDCSetDirichletBoundaries - Set the `IS` defining Dirichlet boundaries for the global problem.
6903b03a366Sstefano_zampini 
691785d1243SStefano Zampini   Collective
6923b03a366Sstefano_zampini 
6933b03a366Sstefano_zampini   Input Parameters:
6943b03a366Sstefano_zampini + pc                  - the preconditioning context
69520f4b53cSBarry Smith - DirichletBoundaries - parallel `IS` defining the Dirichlet boundaries
6963b03a366Sstefano_zampini 
6973b03a366Sstefano_zampini   Level: intermediate
6983b03a366Sstefano_zampini 
699f1580f4eSBarry Smith   Note:
700f1580f4eSBarry Smith   Provide the information if you used `MatZeroRows()` or `MatZeroRowsColumns()`. Any process can list any global node
7013b03a366Sstefano_zampini 
702562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDirichletBoundariesLocal()`, `MatZeroRows()`, `MatZeroRowsColumns()`
7033b03a366Sstefano_zampini @*/
704d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc, IS DirichletBoundaries)
705d71ae5a4SJacob Faibussowitsch {
7063b03a366Sstefano_zampini   PetscFunctionBegin;
7073b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
708674ae819SStefano Zampini   PetscValidHeaderSpecific(DirichletBoundaries, IS_CLASSID, 2);
709785d1243SStefano Zampini   PetscCheckSameComm(pc, 1, DirichletBoundaries, 2);
710cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDirichletBoundaries_C", (PC, IS), (pc, DirichletBoundaries));
7113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7123b03a366Sstefano_zampini }
7131e6b0712SBarry Smith 
714d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc, IS DirichletBoundaries)
715d71ae5a4SJacob Faibussowitsch {
7163b03a366Sstefano_zampini   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
71756282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
7183b03a366Sstefano_zampini 
7193b03a366Sstefano_zampini   PetscFunctionBegin;
7209566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)DirichletBoundaries));
72148a46eb9SPierre Jolivet   if (pcbddc->DirichletBoundariesLocal) PetscCall(ISEqual(DirichletBoundaries, pcbddc->DirichletBoundariesLocal, &isequal));
722a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
7239566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal));
7249566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundaries));
725785d1243SStefano Zampini   pcbddc->DirichletBoundariesLocal = DirichletBoundaries;
72656282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7283b03a366Sstefano_zampini }
7293b03a366Sstefano_zampini 
7303b03a366Sstefano_zampini /*@
73198ad52f2SBarry Smith   PCBDDCSetDirichletBoundariesLocal - Set the `IS` defining Dirichlet boundaries for the global problem in local ordering.
7323b03a366Sstefano_zampini 
733785d1243SStefano Zampini   Collective
7343b03a366Sstefano_zampini 
7353b03a366Sstefano_zampini   Input Parameters:
7363b03a366Sstefano_zampini + pc                  - the preconditioning context
73720f4b53cSBarry Smith - DirichletBoundaries - parallel `IS` defining the Dirichlet boundaries (in local ordering)
7383b03a366Sstefano_zampini 
7393b03a366Sstefano_zampini   Level: intermediate
7403b03a366Sstefano_zampini 
741562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDirichletBoundaries()`, `MatZeroRows()`, `MatZeroRowsColumns()`
7423b03a366Sstefano_zampini @*/
743d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc, IS DirichletBoundaries)
744d71ae5a4SJacob Faibussowitsch {
7453b03a366Sstefano_zampini   PetscFunctionBegin;
7463b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
7473b03a366Sstefano_zampini   PetscValidHeaderSpecific(DirichletBoundaries, IS_CLASSID, 2);
74882ba6b80SStefano Zampini   PetscCheckSameComm(pc, 1, DirichletBoundaries, 2);
749cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDirichletBoundariesLocal_C", (PC, IS), (pc, DirichletBoundaries));
7503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7513b03a366Sstefano_zampini }
7523b03a366Sstefano_zampini 
753d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc, IS NeumannBoundaries)
754d71ae5a4SJacob Faibussowitsch {
7550c7d97c5SJed Brown   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
75656282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
7570c7d97c5SJed Brown 
7580c7d97c5SJed Brown   PetscFunctionBegin;
7599566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries));
76048a46eb9SPierre Jolivet   if (pcbddc->NeumannBoundaries) PetscCall(ISEqual(NeumannBoundaries, pcbddc->NeumannBoundaries, &isequal));
761a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
7629566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal));
7639566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundaries));
76436e030ebSStefano Zampini   pcbddc->NeumannBoundaries = NeumannBoundaries;
76556282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7670c7d97c5SJed Brown }
7681e6b0712SBarry Smith 
76957527edcSJed Brown /*@
77098ad52f2SBarry Smith   PCBDDCSetNeumannBoundaries - Set the `IS` defining Neumann boundaries for the global problem.
77157527edcSJed Brown 
772c3339decSBarry Smith   Collective
77357527edcSJed Brown 
77457527edcSJed Brown   Input Parameters:
77557527edcSJed Brown + pc                - the preconditioning context
77620f4b53cSBarry Smith - NeumannBoundaries - parallel `IS` defining the Neumann boundaries
77757527edcSJed Brown 
77857527edcSJed Brown   Level: intermediate
77957527edcSJed Brown 
780f1580f4eSBarry Smith   Note:
7810f202f7eSStefano Zampini   Any process can list any global node
78257527edcSJed Brown 
783562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetNeumannBoundariesLocal()`
78457527edcSJed Brown @*/
785d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc, IS NeumannBoundaries)
786d71ae5a4SJacob Faibussowitsch {
7870c7d97c5SJed Brown   PetscFunctionBegin;
7880c7d97c5SJed Brown   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
789674ae819SStefano Zampini   PetscValidHeaderSpecific(NeumannBoundaries, IS_CLASSID, 2);
790785d1243SStefano Zampini   PetscCheckSameComm(pc, 1, NeumannBoundaries, 2);
791cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetNeumannBoundaries_C", (PC, IS), (pc, NeumannBoundaries));
7923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
79353cdbc3dSStefano Zampini }
7941e6b0712SBarry Smith 
795d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc, IS NeumannBoundaries)
796d71ae5a4SJacob Faibussowitsch {
7970c7d97c5SJed Brown   PC_BDDC  *pcbddc  = (PC_BDDC *)pc->data;
79856282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
7990c7d97c5SJed Brown 
8000c7d97c5SJed Brown   PetscFunctionBegin;
8019566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries));
80248a46eb9SPierre Jolivet   if (pcbddc->NeumannBoundariesLocal) PetscCall(ISEqual(NeumannBoundaries, pcbddc->NeumannBoundariesLocal, &isequal));
803a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
8049566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal));
8059566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundaries));
806785d1243SStefano Zampini   pcbddc->NeumannBoundariesLocal = NeumannBoundaries;
80756282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
8083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8090c7d97c5SJed Brown }
8100c7d97c5SJed Brown 
8110c7d97c5SJed Brown /*@
81298ad52f2SBarry Smith   PCBDDCSetNeumannBoundariesLocal - Set the `IS` defining Neumann boundaries for the global problem in local ordering.
8130c7d97c5SJed Brown 
814785d1243SStefano Zampini   Collective
8150c7d97c5SJed Brown 
8160c7d97c5SJed Brown   Input Parameters:
8170c7d97c5SJed Brown + pc                - the preconditioning context
81820f4b53cSBarry Smith - NeumannBoundaries - parallel `IS` defining the subdomain part of Neumann boundaries (in local ordering)
8190c7d97c5SJed Brown 
8200c7d97c5SJed Brown   Level: intermediate
8210c7d97c5SJed Brown 
822562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCGetDirichletBoundaries()`
8230c7d97c5SJed Brown @*/
824d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc, IS NeumannBoundaries)
825d71ae5a4SJacob Faibussowitsch {
8260c7d97c5SJed Brown   PetscFunctionBegin;
8270c7d97c5SJed Brown   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
8280c7d97c5SJed Brown   PetscValidHeaderSpecific(NeumannBoundaries, IS_CLASSID, 2);
82982ba6b80SStefano Zampini   PetscCheckSameComm(pc, 1, NeumannBoundaries, 2);
830cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetNeumannBoundariesLocal_C", (PC, IS), (pc, NeumannBoundaries));
8313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
83253cdbc3dSStefano Zampini }
83353cdbc3dSStefano Zampini 
834d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc, IS *DirichletBoundaries)
835d71ae5a4SJacob Faibussowitsch {
836da1bb401SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
837da1bb401SStefano Zampini 
838da1bb401SStefano Zampini   PetscFunctionBegin;
839da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
8403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
841da1bb401SStefano Zampini }
8421e6b0712SBarry Smith 
843da1bb401SStefano Zampini /*@
844f1580f4eSBarry Smith   PCBDDCGetDirichletBoundaries - Get parallel `IS` for Dirichlet boundaries
845da1bb401SStefano Zampini 
846785d1243SStefano Zampini   Collective
847785d1243SStefano Zampini 
848f1580f4eSBarry Smith   Input Parameter:
849785d1243SStefano Zampini . pc - the preconditioning context
850785d1243SStefano Zampini 
851f1580f4eSBarry Smith   Output Parameter:
852785d1243SStefano Zampini . DirichletBoundaries - index set defining the Dirichlet boundaries
853785d1243SStefano Zampini 
854785d1243SStefano Zampini   Level: intermediate
855785d1243SStefano Zampini 
856f1580f4eSBarry Smith   Note:
857f1580f4eSBarry Smith   The `IS` returned (if any) is the same passed in earlier by the user with `PCBDDCSetDirichletBoundaries()`
858785d1243SStefano Zampini 
859562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDirichletBoundaries()`
860785d1243SStefano Zampini @*/
861d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc, IS *DirichletBoundaries)
862d71ae5a4SJacob Faibussowitsch {
863785d1243SStefano Zampini   PetscFunctionBegin;
864785d1243SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
865cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetDirichletBoundaries_C", (PC, IS *), (pc, DirichletBoundaries));
8663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
867785d1243SStefano Zampini }
868785d1243SStefano Zampini 
869d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc, IS *DirichletBoundaries)
870d71ae5a4SJacob Faibussowitsch {
871785d1243SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
872785d1243SStefano Zampini 
873785d1243SStefano Zampini   PetscFunctionBegin;
874785d1243SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundariesLocal;
8753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
876785d1243SStefano Zampini }
877785d1243SStefano Zampini 
878da1bb401SStefano Zampini /*@
879f1580f4eSBarry Smith   PCBDDCGetDirichletBoundariesLocal - Get parallel `IS` for Dirichlet boundaries (in local ordering)
880da1bb401SStefano Zampini 
881785d1243SStefano Zampini   Collective
882da1bb401SStefano Zampini 
883f1580f4eSBarry Smith   Input Parameter:
88428509bceSStefano Zampini . pc - the preconditioning context
885da1bb401SStefano Zampini 
886f1580f4eSBarry Smith   Output Parameter:
88728509bceSStefano Zampini . DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
888da1bb401SStefano Zampini 
889da1bb401SStefano Zampini   Level: intermediate
890da1bb401SStefano Zampini 
891f1580f4eSBarry Smith   Note:
892f1580f4eSBarry Smith   The `IS` returned could be the same passed in earlier by the user (if provided with `PCBDDCSetDirichletBoundariesLocal()`)
893f1580f4eSBarry Smith   or a global-to-local map of the global `IS` (if provided with `PCBDDCSetDirichletBoundaries()`).
894f1580f4eSBarry Smith   In the latter case, the `IS` will be available only after `PCSetUp()`.
895da1bb401SStefano Zampini 
896562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCGetDirichletBoundaries()`, `PCBDDCSetDirichletBoundaries()`
897da1bb401SStefano Zampini @*/
898d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc, IS *DirichletBoundaries)
899d71ae5a4SJacob Faibussowitsch {
900da1bb401SStefano Zampini   PetscFunctionBegin;
901da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
902cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetDirichletBoundariesLocal_C", (PC, IS *), (pc, DirichletBoundaries));
9033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
904da1bb401SStefano Zampini }
9051e6b0712SBarry Smith 
906d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc, IS *NeumannBoundaries)
907d71ae5a4SJacob Faibussowitsch {
90853cdbc3dSStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
90953cdbc3dSStefano Zampini 
91053cdbc3dSStefano Zampini   PetscFunctionBegin;
91153cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
9123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
91353cdbc3dSStefano Zampini }
9141e6b0712SBarry Smith 
91553cdbc3dSStefano Zampini /*@
916f1580f4eSBarry Smith   PCBDDCGetNeumannBoundaries - Get parallel `IS` for Neumann boundaries
91753cdbc3dSStefano Zampini 
918f1580f4eSBarry Smith   Not Collective
919785d1243SStefano Zampini 
920f1580f4eSBarry Smith   Input Parameter:
921785d1243SStefano Zampini . pc - the preconditioning context
922785d1243SStefano Zampini 
923f1580f4eSBarry Smith   Output Parameter:
924785d1243SStefano Zampini . NeumannBoundaries - index set defining the Neumann boundaries
925785d1243SStefano Zampini 
926785d1243SStefano Zampini   Level: intermediate
927785d1243SStefano Zampini 
928f1580f4eSBarry Smith   Note:
929f1580f4eSBarry Smith   The `IS` returned (if any) is the same passed in earlier by the user with `PCBDDCSetNeumannBoundaries()`
930785d1243SStefano Zampini 
931562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCGetDirichletBoundaries()`, `PCBDDCSetDirichletBoundaries()`
932785d1243SStefano Zampini @*/
933d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc, IS *NeumannBoundaries)
934d71ae5a4SJacob Faibussowitsch {
935785d1243SStefano Zampini   PetscFunctionBegin;
936785d1243SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
937cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetNeumannBoundaries_C", (PC, IS *), (pc, NeumannBoundaries));
9383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
939785d1243SStefano Zampini }
940785d1243SStefano Zampini 
941d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc, IS *NeumannBoundaries)
942d71ae5a4SJacob Faibussowitsch {
943785d1243SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
944785d1243SStefano Zampini 
945785d1243SStefano Zampini   PetscFunctionBegin;
946785d1243SStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundariesLocal;
9473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
948785d1243SStefano Zampini }
949785d1243SStefano Zampini 
95053cdbc3dSStefano Zampini /*@
951f1580f4eSBarry Smith   PCBDDCGetNeumannBoundariesLocal - Get parallel `IS` for Neumann boundaries (in local ordering)
95253cdbc3dSStefano Zampini 
953f1580f4eSBarry Smith   Not Collective
95453cdbc3dSStefano Zampini 
955f1580f4eSBarry Smith   Input Parameter:
95628509bceSStefano Zampini . pc - the preconditioning context
95753cdbc3dSStefano Zampini 
958f1580f4eSBarry Smith   Output Parameter:
95928509bceSStefano Zampini . NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
96053cdbc3dSStefano Zampini 
96153cdbc3dSStefano Zampini   Level: intermediate
96253cdbc3dSStefano Zampini 
963f1580f4eSBarry Smith   Note:
964f1580f4eSBarry Smith   The `IS` returned could be the same passed in earlier by the user (if provided with `PCBDDCSetNeumannBoundariesLocal()`
965f1580f4eSBarry Smith   or a global-to-local map of the global `IS` (if provided with `PCBDDCSetNeumannBoundaries()`).
966f1580f4eSBarry Smith   In the latter case, the `IS` will be available after `PCSetUp()`.
96753cdbc3dSStefano Zampini 
968562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCSetNeumannBoundariesLocal)`, `PCBDDCGetNeumannBoundaries()`
96953cdbc3dSStefano Zampini @*/
970d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc, IS *NeumannBoundaries)
971d71ae5a4SJacob Faibussowitsch {
97253cdbc3dSStefano Zampini   PetscFunctionBegin;
97353cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
974cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCGetNeumannBoundariesLocal_C", (PC, IS *), (pc, NeumannBoundaries));
9753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9760c7d97c5SJed Brown }
9771e6b0712SBarry Smith 
978d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs, const PetscInt xadj[], const PetscInt adjncy[], PetscCopyMode copymode)
979d71ae5a4SJacob Faibussowitsch {
98036e030ebSStefano Zampini   PC_BDDC    *pcbddc    = (PC_BDDC *)pc->data;
981da1bb401SStefano Zampini   PCBDDCGraph mat_graph = pcbddc->mat_graph;
98256282151SStefano Zampini   PetscBool   same_data = PETSC_FALSE;
98336e030ebSStefano Zampini 
98436e030ebSStefano Zampini   PetscFunctionBegin;
9858687889aSStefano Zampini   if (!nvtxs) {
98604194a47SStefano Zampini     if (copymode == PETSC_OWN_POINTER) {
9879566063dSJacob Faibussowitsch       PetscCall(PetscFree(xadj));
9889566063dSJacob Faibussowitsch       PetscCall(PetscFree(adjncy));
98904194a47SStefano Zampini     }
9909566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphResetCSR(mat_graph));
9913ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
9928687889aSStefano Zampini   }
99366da6bd7Sstefano_zampini   if (mat_graph->nvtxs == nvtxs && mat_graph->freecsr) { /* we own the data */
99456282151SStefano Zampini     if (mat_graph->xadj == xadj && mat_graph->adjncy == adjncy) same_data = PETSC_TRUE;
99556282151SStefano Zampini     if (!same_data && mat_graph->xadj[nvtxs] == xadj[nvtxs]) {
9969566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(xadj, mat_graph->xadj, nvtxs + 1, &same_data));
99748a46eb9SPierre Jolivet       if (same_data) PetscCall(PetscArraycmp(adjncy, mat_graph->adjncy, xadj[nvtxs], &same_data));
99856282151SStefano Zampini     }
99956282151SStefano Zampini   }
100056282151SStefano Zampini   if (!same_data) {
1001674ae819SStefano Zampini     /* free old CSR */
10029566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphResetCSR(mat_graph));
1003674ae819SStefano Zampini     /* get CSR into graph structure */
1004da1bb401SStefano Zampini     if (copymode == PETSC_COPY_VALUES) {
10059566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvtxs + 1, &mat_graph->xadj));
10069566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(xadj[nvtxs], &mat_graph->adjncy));
10079566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(mat_graph->xadj, xadj, nvtxs + 1));
10089566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(mat_graph->adjncy, adjncy, xadj[nvtxs]));
1009a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1010da1bb401SStefano Zampini     } else if (copymode == PETSC_OWN_POINTER) {
10111a83f524SJed Brown       mat_graph->xadj    = (PetscInt *)xadj;
10121a83f524SJed Brown       mat_graph->adjncy  = (PetscInt *)adjncy;
1013a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1014a1dbd327SStefano Zampini     } else if (copymode == PETSC_USE_POINTER) {
1015a1dbd327SStefano Zampini       mat_graph->xadj    = (PetscInt *)xadj;
1016a1dbd327SStefano Zampini       mat_graph->adjncy  = (PetscInt *)adjncy;
1017a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_FALSE;
101863a3b9bcSJacob Faibussowitsch     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported copy mode %d", copymode);
1019575ad6abSStefano Zampini     mat_graph->nvtxs_csr         = nvtxs;
102056282151SStefano Zampini     pcbddc->recompute_topography = PETSC_TRUE;
102156282151SStefano Zampini   }
10223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
102336e030ebSStefano Zampini }
10241e6b0712SBarry Smith 
102536e030ebSStefano Zampini /*@
102654fffbccSStefano Zampini   PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local degrees of freedom.
102736e030ebSStefano Zampini 
102836e030ebSStefano Zampini   Not collective
102936e030ebSStefano Zampini 
103036e030ebSStefano Zampini   Input Parameters:
103154fffbccSStefano Zampini + pc       - the preconditioning context.
103254fffbccSStefano Zampini . nvtxs    - number of local vertices of the graph (i.e., the number of local dofs).
103304c3f3b8SBarry Smith . xadj     - CSR format row pointers for the connectivity of the dofs
103404c3f3b8SBarry Smith . adjncy   - CSR format column pointers for the connectivity of the dofs
1035f1580f4eSBarry Smith - copymode - supported modes are `PETSC_COPY_VALUES`, `PETSC_USE_POINTER` or `PETSC_OWN_POINTER`.
103636e030ebSStefano Zampini 
103736e030ebSStefano Zampini   Level: intermediate
103836e030ebSStefano Zampini 
1039f1580f4eSBarry Smith   Note:
104095452b02SPatrick Sanan   A dof is considered connected with all local dofs if xadj[dof+1]-xadj[dof] == 1 and adjncy[xadj[dof]] is negative.
104136e030ebSStefano Zampini 
1042562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PetscCopyMode`
104336e030ebSStefano Zampini @*/
1044d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc, PetscInt nvtxs, const PetscInt xadj[], const PetscInt adjncy[], PetscCopyMode copymode)
1045d71ae5a4SJacob Faibussowitsch {
10460a545947SLisandro Dalcin   void (*f)(void) = NULL;
104736e030ebSStefano Zampini 
104836e030ebSStefano Zampini   PetscFunctionBegin;
104936e030ebSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
10508687889aSStefano Zampini   if (nvtxs) {
10514f572ea9SToby Isaac     PetscAssertPointer(xadj, 3);
10524f572ea9SToby Isaac     if (xadj[nvtxs]) PetscAssertPointer(adjncy, 4);
10538687889aSStefano Zampini   }
1054cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetLocalAdjacencyGraph_C", (PC, PetscInt, const PetscInt[], const PetscInt[], PetscCopyMode), (pc, nvtxs, xadj, adjncy, copymode));
1055575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
10569566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", &f));
1057575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
10589566063dSJacob Faibussowitsch     PetscCall(PetscFree(xadj));
10599566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjncy));
1060da1bb401SStefano Zampini   }
10613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
106236e030ebSStefano Zampini }
10631e6b0712SBarry Smith 
1064d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc, PetscInt n_is, IS ISForDofs[])
1065d71ae5a4SJacob Faibussowitsch {
106663602bcaSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC *)pc->data;
106763602bcaSStefano Zampini   PetscInt  i;
106856282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
106963602bcaSStefano Zampini 
107063602bcaSStefano Zampini   PetscFunctionBegin;
107156282151SStefano Zampini   if (pcbddc->n_ISForDofsLocal == n_is) {
107256282151SStefano Zampini     for (i = 0; i < n_is; i++) {
107356282151SStefano Zampini       PetscBool isequalt;
10749566063dSJacob Faibussowitsch       PetscCall(ISEqual(ISForDofs[i], pcbddc->ISForDofsLocal[i], &isequalt));
107556282151SStefano Zampini       if (!isequalt) break;
107656282151SStefano Zampini     }
107756282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
107856282151SStefano Zampini   }
107948a46eb9SPierre Jolivet   for (i = 0; i < n_is; i++) PetscCall(PetscObjectReference((PetscObject)ISForDofs[i]));
108063602bcaSStefano Zampini   /* Destroy ISes if they were already set */
108148a46eb9SPierre Jolivet   for (i = 0; i < pcbddc->n_ISForDofsLocal; i++) PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i]));
10829566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofsLocal));
1083a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
108448a46eb9SPierre Jolivet   for (i = 0; i < pcbddc->n_ISForDofs; i++) PetscCall(ISDestroy(&pcbddc->ISForDofs[i]));
10859566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofs));
108663602bcaSStefano Zampini   pcbddc->n_ISForDofs = 0;
108763602bcaSStefano Zampini   /* allocate space then set */
108848a46eb9SPierre Jolivet   if (n_is) PetscCall(PetscMalloc1(n_is, &pcbddc->ISForDofsLocal));
1089ad540459SPierre Jolivet   for (i = 0; i < n_is; i++) pcbddc->ISForDofsLocal[i] = ISForDofs[i];
109063602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = n_is;
109163602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
109256282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
10933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
109463602bcaSStefano Zampini }
109563602bcaSStefano Zampini 
109663602bcaSStefano Zampini /*@
109798ad52f2SBarry Smith   PCBDDCSetDofsSplittingLocal - Set the `IS` defining fields of the local subdomain matrix
109863602bcaSStefano Zampini 
109963602bcaSStefano Zampini   Collective
110063602bcaSStefano Zampini 
110163602bcaSStefano Zampini   Input Parameters:
110263602bcaSStefano Zampini + pc        - the preconditioning context
110398ad52f2SBarry Smith . n_is      - number of index sets defining the fields, must be the same on all MPI processes
1104f1580f4eSBarry Smith - ISForDofs - array of `IS` describing the fields in local ordering
110563602bcaSStefano Zampini 
110663602bcaSStefano Zampini   Level: intermediate
110763602bcaSStefano Zampini 
1108f1580f4eSBarry Smith   Note:
1109feefa0e1SJacob Faibussowitsch   Not all nodes need to be listed, unlisted nodes will belong to the complement field.
111063602bcaSStefano Zampini 
1111562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDofsSplitting()`
111263602bcaSStefano Zampini @*/
1113d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc, PetscInt n_is, IS ISForDofs[])
1114d71ae5a4SJacob Faibussowitsch {
111563602bcaSStefano Zampini   PetscInt i;
111663602bcaSStefano Zampini 
111763602bcaSStefano Zampini   PetscFunctionBegin;
111863602bcaSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
111963602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc, n_is, 2);
112063602bcaSStefano Zampini   for (i = 0; i < n_is; i++) {
112163602bcaSStefano Zampini     PetscCheckSameComm(pc, 1, ISForDofs[i], 3);
112263602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i], IS_CLASSID, 3);
112363602bcaSStefano Zampini   }
1124cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDofsSplittingLocal_C", (PC, PetscInt, IS[]), (pc, n_is, ISForDofs));
11253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
112663602bcaSStefano Zampini }
112763602bcaSStefano Zampini 
1128d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc, PetscInt n_is, IS ISForDofs[])
1129d71ae5a4SJacob Faibussowitsch {
11309c0446d6SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC *)pc->data;
11319c0446d6SStefano Zampini   PetscInt  i;
113256282151SStefano Zampini   PetscBool isequal = PETSC_FALSE;
11339c0446d6SStefano Zampini 
11349c0446d6SStefano Zampini   PetscFunctionBegin;
113556282151SStefano Zampini   if (pcbddc->n_ISForDofs == n_is) {
113656282151SStefano Zampini     for (i = 0; i < n_is; i++) {
113756282151SStefano Zampini       PetscBool isequalt;
11389566063dSJacob Faibussowitsch       PetscCall(ISEqual(ISForDofs[i], pcbddc->ISForDofs[i], &isequalt));
113956282151SStefano Zampini       if (!isequalt) break;
114056282151SStefano Zampini     }
114156282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
114256282151SStefano Zampini   }
114348a46eb9SPierre Jolivet   for (i = 0; i < n_is; i++) PetscCall(PetscObjectReference((PetscObject)ISForDofs[i]));
1144da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
114548a46eb9SPierre Jolivet   for (i = 0; i < pcbddc->n_ISForDofs; i++) PetscCall(ISDestroy(&pcbddc->ISForDofs[i]));
11469566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofs));
1147a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
114848a46eb9SPierre Jolivet   for (i = 0; i < pcbddc->n_ISForDofsLocal; i++) PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i]));
11499566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofsLocal));
115063602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = 0;
1151da1bb401SStefano Zampini   /* allocate space then set */
115248a46eb9SPierre Jolivet   if (n_is) PetscCall(PetscMalloc1(n_is, &pcbddc->ISForDofs));
1153ad540459SPierre Jolivet   for (i = 0; i < n_is; i++) pcbddc->ISForDofs[i] = ISForDofs[i];
11549c0446d6SStefano Zampini   pcbddc->n_ISForDofs = n_is;
115563602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
115656282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
11573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11589c0446d6SStefano Zampini }
11591e6b0712SBarry Smith 
11609c0446d6SStefano Zampini /*@
116198ad52f2SBarry Smith   PCBDDCSetDofsSplitting - Set the `IS` defining fields of the global matrix
11629c0446d6SStefano Zampini 
116363602bcaSStefano Zampini   Collective
11649c0446d6SStefano Zampini 
11659c0446d6SStefano Zampini   Input Parameters:
11669c0446d6SStefano Zampini + pc        - the preconditioning context
11670f202f7eSStefano Zampini . n_is      - number of index sets defining the fields
116898ad52f2SBarry Smith - ISForDofs - array of `IS` describing the fields in global ordering
11699c0446d6SStefano Zampini 
11709c0446d6SStefano Zampini   Level: intermediate
11719c0446d6SStefano Zampini 
1172f1580f4eSBarry Smith   Note:
11730f202f7eSStefano Zampini   Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
11749c0446d6SStefano Zampini 
1175562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCSetDofsSplittingLocal()`
11769c0446d6SStefano Zampini @*/
1177d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCSetDofsSplitting(PC pc, PetscInt n_is, IS ISForDofs[])
1178d71ae5a4SJacob Faibussowitsch {
11792b510759SStefano Zampini   PetscInt i;
11809c0446d6SStefano Zampini 
11819c0446d6SStefano Zampini   PetscFunctionBegin;
11829c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
118363602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc, n_is, 2);
11842b510759SStefano Zampini   for (i = 0; i < n_is; i++) {
118563602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i], IS_CLASSID, 3);
1186a011d5a7Sstefano_zampini     PetscCheckSameComm(pc, 1, ISForDofs[i], 3);
11872b510759SStefano Zampini   }
1188cac4c232SBarry Smith   PetscTryMethod(pc, "PCBDDCSetDofsSplitting_C", (PC, PetscInt, IS[]), (pc, n_is, ISForDofs));
11893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11909c0446d6SStefano Zampini }
1191906d46d4SStefano Zampini 
1192d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1193d71ae5a4SJacob Faibussowitsch {
1194534831adSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC *)pc->data;
1195*f4f49eeaSPierre Jolivet   PC_IS    *pcis   = (PC_IS *)pc->data;
11963972b0daSStefano Zampini   Vec       used_vec;
1197fcb54b1cSPierre Jolivet   PetscBool iscg, save_rhs = PETSC_TRUE, benign_correction_computed;
1198534831adSStefano Zampini 
1199534831adSStefano Zampini   PetscFunctionBegin;
12001f4df5f7SStefano Zampini   /* if we are working with CG, one dirichlet solve can be avoided during Krylov iterations */
120185c4d303SStefano Zampini   if (ksp) {
1202fcb54b1cSPierre Jolivet     PetscCall(PetscObjectTypeCompareAny((PetscObject)ksp, &iscg, KSPCG, KSPGROPPCG, KSPPIPECG, KSPPIPELCG, KSPPIPECGRR, ""));
120348a46eb9SPierre Jolivet     if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || !iscg || pc->mat != pc->pmat) PetscCall(PCBDDCSetUseExactDirichlet(pc, PETSC_FALSE));
120485c4d303SStefano Zampini   }
120548a46eb9SPierre Jolivet   if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || pc->mat != pc->pmat) PetscCall(PCBDDCSetUseExactDirichlet(pc, PETSC_FALSE));
12061f4df5f7SStefano Zampini 
120785c4d303SStefano Zampini   /* Creates parallel work vectors used in presolve */
120848a46eb9SPierre Jolivet   if (!pcbddc->original_rhs) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->original_rhs));
120948a46eb9SPierre Jolivet   if (!pcbddc->temp_solution) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->temp_solution));
12108d00608fSStefano Zampini 
121127b6a85dSStefano Zampini   pcbddc->temp_solution_used = PETSC_FALSE;
12123972b0daSStefano Zampini   if (x) {
12139566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)x));
12143972b0daSStefano Zampini     used_vec = x;
12158d00608fSStefano Zampini   } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */
12169566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pcbddc->temp_solution));
12173972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
12189566063dSJacob Faibussowitsch     PetscCall(VecSet(used_vec, 0.0));
121927b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
12209566063dSJacob Faibussowitsch     PetscCall(VecCopy(rhs, pcbddc->original_rhs));
1221266e20e9SStefano Zampini     save_rhs                  = PETSC_FALSE;
1222266e20e9SStefano Zampini     pcbddc->eliminate_dirdofs = PETSC_TRUE;
12233972b0daSStefano Zampini   }
12248efcfb23SStefano Zampini 
12258efcfb23SStefano Zampini   /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */
12263972b0daSStefano Zampini   if (ksp) {
1227a0cb1b98SStefano Zampini     /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */
12289566063dSJacob Faibussowitsch     PetscCall(KSPGetInitialGuessNonzero(ksp, &pcbddc->ksp_guess_nonzero));
122948a46eb9SPierre Jolivet     if (!pcbddc->ksp_guess_nonzero) PetscCall(VecSet(used_vec, 0.0));
12303972b0daSStefano Zampini   }
12313308cffdSStefano Zampini 
12328d00608fSStefano Zampini   pcbddc->rhs_change = PETSC_FALSE;
12333972b0daSStefano Zampini   /* Take into account zeroed rows -> change rhs and store solution removed */
123470c64980SStefano Zampini   if (rhs && pcbddc->eliminate_dirdofs) {
12353975b054SStefano Zampini     IS dirIS = NULL;
12363975b054SStefano Zampini 
1237a07ea27aSStefano Zampini     /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */
12389566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph, &dirIS));
12393975b054SStefano Zampini     if (dirIS) {
1240906d46d4SStefano Zampini       Mat_IS            *matis = (Mat_IS *)pc->pmat->data;
1241785d1243SStefano Zampini       PetscInt           dirsize, i, *is_indices;
12422b095fd8SStefano Zampini       PetscScalar       *array_x;
12432b095fd8SStefano Zampini       const PetscScalar *array_diagonal;
1244785d1243SStefano Zampini 
12459566063dSJacob Faibussowitsch       PetscCall(MatGetDiagonal(pc->pmat, pcis->vec1_global));
12469566063dSJacob Faibussowitsch       PetscCall(VecPointwiseDivide(pcis->vec1_global, rhs, pcis->vec1_global));
12479566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_global, pcis->vec2_N, INSERT_VALUES, SCATTER_FORWARD));
12489566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_global, pcis->vec2_N, INSERT_VALUES, SCATTER_FORWARD));
12499566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx, used_vec, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD));
12509566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx, used_vec, pcis->vec1_N, INSERT_VALUES, SCATTER_FORWARD));
12519566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(dirIS, &dirsize));
12529566063dSJacob Faibussowitsch       PetscCall(VecGetArray(pcis->vec1_N, &array_x));
12539566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(pcis->vec2_N, &array_diagonal));
12549566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(dirIS, (const PetscInt **)&is_indices));
12552fa5cd67SKarl Rupp       for (i = 0; i < dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
12569566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(dirIS, (const PetscInt **)&is_indices));
12579566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(pcis->vec2_N, &array_diagonal));
12589566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(pcis->vec1_N, &array_x));
12599566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx, pcis->vec1_N, used_vec, INSERT_VALUES, SCATTER_REVERSE));
12609566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx, pcis->vec1_N, used_vec, INSERT_VALUES, SCATTER_REVERSE));
12618d00608fSStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
12629566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&dirIS));
12638efcfb23SStefano Zampini     }
1264a07ea27aSStefano Zampini   }
1265b76ba322SStefano Zampini 
12668efcfb23SStefano Zampini   /* remove the computed solution or the initial guess from the rhs */
12678d00608fSStefano Zampini   if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero)) {
126827b6a85dSStefano Zampini     /* save the original rhs */
126927b6a85dSStefano Zampini     if (save_rhs) {
12709566063dSJacob Faibussowitsch       PetscCall(VecSwap(rhs, pcbddc->original_rhs));
127127b6a85dSStefano Zampini       save_rhs = PETSC_FALSE;
12728d00608fSStefano Zampini     }
12738d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
12749566063dSJacob Faibussowitsch     PetscCall(VecScale(used_vec, -1.0));
12759566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(pc->mat, used_vec, pcbddc->original_rhs, rhs));
12769566063dSJacob Faibussowitsch     PetscCall(VecScale(used_vec, -1.0));
12779566063dSJacob Faibussowitsch     PetscCall(VecCopy(used_vec, pcbddc->temp_solution));
127827b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
12791baa6e33SBarry Smith     if (ksp) PetscCall(KSPSetInitialGuessNonzero(ksp, PETSC_FALSE));
12803308cffdSStefano Zampini   }
12819566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&used_vec));
1282b76ba322SStefano Zampini 
1283fc17d649SStefano Zampini   /* compute initial vector in benign space if needed
128427b6a85dSStefano Zampini      and remove non-benign solution from the rhs */
128527b6a85dSStefano Zampini   benign_correction_computed = PETSC_FALSE;
128608af2428SStefano Zampini   if (rhs && pcbddc->benign_compute_correction && (pcbddc->benign_have_null || pcbddc->benign_apply_coarse_only)) {
12871f4df5f7SStefano Zampini     /* compute u^*_h using ideas similar to those in Xuemin Tu's PhD thesis (see Section 4.8.1)
12881f4df5f7SStefano Zampini        Recursively apply BDDC in the multilevel case */
128948a46eb9SPierre Jolivet     if (!pcbddc->benign_vec) PetscCall(VecDuplicate(rhs, &pcbddc->benign_vec));
1290c69e9cc1SStefano Zampini     /* keep applying coarse solver unless we no longer have benign subdomains */
1291c69e9cc1SStefano Zampini     pcbddc->benign_apply_coarse_only = pcbddc->benign_have_null ? PETSC_TRUE : PETSC_FALSE;
129227b6a85dSStefano Zampini     if (!pcbddc->benign_skip_correction) {
12939566063dSJacob Faibussowitsch       PetscCall(PCApply_BDDC(pc, rhs, pcbddc->benign_vec));
12943bca92a6SStefano Zampini       benign_correction_computed = PETSC_TRUE;
12951baa6e33SBarry Smith       if (pcbddc->temp_solution_used) PetscCall(VecAXPY(pcbddc->temp_solution, 1.0, pcbddc->benign_vec));
12969566063dSJacob Faibussowitsch       PetscCall(VecScale(pcbddc->benign_vec, -1.0));
129727b6a85dSStefano Zampini       /* store the original rhs if not done earlier */
12981baa6e33SBarry Smith       if (save_rhs) PetscCall(VecSwap(rhs, pcbddc->original_rhs));
129927b6a85dSStefano Zampini       if (pcbddc->rhs_change) {
13009566063dSJacob Faibussowitsch         PetscCall(MatMultAdd(pc->mat, pcbddc->benign_vec, rhs, rhs));
130127b6a85dSStefano Zampini       } else {
13029566063dSJacob Faibussowitsch         PetscCall(MatMultAdd(pc->mat, pcbddc->benign_vec, pcbddc->original_rhs, rhs));
130327b6a85dSStefano Zampini       }
13040369aaf7SStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
130527b6a85dSStefano Zampini     }
130627b6a85dSStefano Zampini     pcbddc->benign_apply_coarse_only = PETSC_FALSE;
13074df7a6bfSStefano Zampini   } else {
13089566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&pcbddc->benign_vec));
13090369aaf7SStefano Zampini   }
13102d4c4fecSStefano Zampini 
13112d4c4fecSStefano Zampini   /* dbg output */
1312a198735bSStefano Zampini   if (pcbddc->dbg_flag && benign_correction_computed) {
13131f4df5f7SStefano Zampini     Vec v;
1314c69e9cc1SStefano Zampini 
13159566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_global, &v));
1316c69e9cc1SStefano Zampini     if (pcbddc->ChangeOfBasisMatrix) {
13179566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, rhs, v));
1318c69e9cc1SStefano Zampini     } else {
13199566063dSJacob Faibussowitsch       PetscCall(VecCopy(rhs, v));
1320c69e9cc1SStefano Zampini     }
13219566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, v, PETSC_TRUE));
132263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer, "LEVEL %" PetscInt_FMT ": is the correction benign?\n", pcbddc->current_level));
13239566063dSJacob Faibussowitsch     PetscCall(PetscScalarView(pcbddc->benign_n, pcbddc->benign_p0, pcbddc->dbg_viewer));
13249566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
13259566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&v));
13261f4df5f7SStefano Zampini   }
13270369aaf7SStefano Zampini 
13280369aaf7SStefano Zampini   /* set initial guess if using PCG */
13298ae0ca82SStefano Zampini   pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
13300369aaf7SStefano Zampini   if (x && pcbddc->use_exact_dirichlet_trick) {
13319566063dSJacob Faibussowitsch     PetscCall(VecSet(x, 0.0));
13321dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
133327b6a85dSStefano Zampini       if (benign_correction_computed) { /* we have already saved the changed rhs */
13349566063dSJacob Faibussowitsch         PetscCall(VecLockReadPop(pcis->vec1_global));
13351dd7afcfSStefano Zampini       } else {
13369566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, rhs, pcis->vec1_global));
13371dd7afcfSStefano Zampini       }
13389566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_global, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
13399566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_global, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
13401dd7afcfSStefano Zampini     } else {
13419566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D, rhs, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
13429566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D, rhs, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
13431dd7afcfSStefano Zampini     }
13449566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
13459566063dSJacob Faibussowitsch     PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D));
13469566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
13479566063dSJacob Faibussowitsch     PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D));
13481dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
13499566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_global, 0.));
13509566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, pcis->vec1_global, INSERT_VALUES, SCATTER_REVERSE));
13519566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, pcis->vec1_global, INSERT_VALUES, SCATTER_REVERSE));
13529566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcis->vec1_global, x));
13531dd7afcfSStefano Zampini     } else {
13549566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, x, INSERT_VALUES, SCATTER_REVERSE));
13559566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, x, INSERT_VALUES, SCATTER_REVERSE));
13561dd7afcfSStefano Zampini     }
13571baa6e33SBarry Smith     if (ksp) PetscCall(KSPSetInitialGuessNonzero(ksp, PETSC_TRUE));
13588ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_TRUE;
1359266e20e9SStefano Zampini   } else if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior && benign_correction_computed && pcbddc->use_exact_dirichlet_trick) {
13609566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(pcis->vec1_global));
13610369aaf7SStefano Zampini   }
13623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1363534831adSStefano Zampini }
1364906d46d4SStefano Zampini 
1365d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1366d71ae5a4SJacob Faibussowitsch {
1367534831adSStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
1368534831adSStefano Zampini 
1369534831adSStefano Zampini   PetscFunctionBegin;
13703972b0daSStefano Zampini   /* add solution removed in presolve */
13716bcfc461SStefano Zampini   if (x && pcbddc->rhs_change) {
137227b6a85dSStefano Zampini     if (pcbddc->temp_solution_used) {
13739566063dSJacob Faibussowitsch       PetscCall(VecAXPY(x, 1.0, pcbddc->temp_solution));
1374af140850Sstefano_zampini     } else if (pcbddc->benign_compute_correction && pcbddc->benign_vec) {
13759566063dSJacob Faibussowitsch       PetscCall(VecAXPY(x, -1.0, pcbddc->benign_vec));
13763425bc38SStefano Zampini     }
1377af140850Sstefano_zampini     /* restore to original state (not for FETI-DP) */
1378af140850Sstefano_zampini     if (ksp) pcbddc->temp_solution_used = PETSC_FALSE;
137927b6a85dSStefano Zampini   }
138027b6a85dSStefano Zampini 
1381266e20e9SStefano Zampini   /* restore rhs to its original state (not needed for FETI-DP) */
13828d00608fSStefano Zampini   if (rhs && pcbddc->rhs_change) {
13839566063dSJacob Faibussowitsch     PetscCall(VecSwap(rhs, pcbddc->original_rhs));
13848d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_FALSE;
1385af140850Sstefano_zampini   }
13868efcfb23SStefano Zampini   /* restore ksp guess state */
13878efcfb23SStefano Zampini   if (ksp) {
13889566063dSJacob Faibussowitsch     PetscCall(KSPSetInitialGuessNonzero(ksp, pcbddc->ksp_guess_nonzero));
13898ae0ca82SStefano Zampini     /* reset flag for exact dirichlet trick */
13908ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
1391af140850Sstefano_zampini   }
13923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1393534831adSStefano Zampini }
1394af140850Sstefano_zampini 
139566976f2fSJacob Faibussowitsch static PetscErrorCode PCSetUp_BDDC(PC pc)
1396d71ae5a4SJacob Faibussowitsch {
13970c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC *)pc->data;
1398c703fcc7SStefano Zampini   PCBDDCSubSchurs sub_schurs;
13995e8657edSStefano Zampini   Mat_IS         *matis;
140008122e43SStefano Zampini   MatNullSpace    nearnullspace;
140135509ce9Sstefano_zampini   Mat             lA;
140235509ce9Sstefano_zampini   IS              lP, zerodiag = NULL;
140391e8d312SStefano Zampini   PetscInt        nrows, ncols;
140486bfa4cfSStefano Zampini   PetscMPIInt     size;
1405c703fcc7SStefano Zampini   PetscBool       computesubschurs;
14068de1fae6SStefano Zampini   PetscBool       computeconstraintsmatrix;
14073b03f7bbSStefano Zampini   PetscBool       new_nearnullspace_provided, ismatis, rl;
1408b94d7dedSBarry Smith   PetscBool       isset, issym, isspd;
14090c7d97c5SJed Brown 
14100c7d97c5SJed Brown   PetscFunctionBegin;
14119566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATIS, &ismatis));
141228b400f6SJacob Faibussowitsch   PetscCheck(ismatis, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "PCBDDC preconditioner requires matrix of type MATIS");
14139566063dSJacob Faibussowitsch   PetscCall(MatGetSize(pc->pmat, &nrows, &ncols));
14147827d75bSBarry Smith   PetscCheck(nrows == ncols, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "PCBDDC preconditioner requires a square preconditioning matrix");
14159566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc), &size));
141686bfa4cfSStefano Zampini 
14175e8657edSStefano Zampini   matis = (Mat_IS *)pc->pmat->data;
1418f4ddd8eeSStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */
14193b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
142071582508SStefano Zampini      Also, BDDC builds its own KSP for the Dirichlet problem */
14213b03f7bbSStefano Zampini   rl = pcbddc->recompute_topography;
14223b03f7bbSStefano Zampini   if (!pc->setupcalled || pc->flag == DIFFERENT_NONZERO_PATTERN) rl = PETSC_TRUE;
14231c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&rl, &pcbddc->recompute_topography, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)pc)));
1424c83e1ba7SStefano Zampini   if (pcbddc->recompute_topography) {
1425c83e1ba7SStefano Zampini     pcbddc->graphanalyzed    = PETSC_FALSE;
1426c83e1ba7SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1427c83e1ba7SStefano Zampini   } else {
14288de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_FALSE;
1429c83e1ba7SStefano Zampini   }
1430b087196eSStefano Zampini 
1431b087196eSStefano Zampini   /* check parameters' compatibility */
1432b7ab4a40SStefano Zampini   if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE;
1433bd2a564bSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_threshold[0] != 0.0 || pcbddc->adaptive_threshold[1] != 0.0);
143486bfa4cfSStefano Zampini   pcbddc->use_deluxe_scaling   = (PetscBool)(pcbddc->use_deluxe_scaling && size > 1);
143586bfa4cfSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_selection && size > 1);
1436bf3a8328SStefano Zampini   pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined);
1437862806e4SStefano Zampini   if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE;
1438862806e4SStefano Zampini 
14395a95e1ceSStefano Zampini   computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling);
144016909a7fSStefano Zampini 
144171582508SStefano Zampini   /* activate all connected components if the netflux has been requested */
1442bb05f991SStefano Zampini   if (pcbddc->compute_nonetflux) {
1443bb05f991SStefano Zampini     pcbddc->use_vertices = PETSC_TRUE;
1444bb05f991SStefano Zampini     pcbddc->use_edges    = PETSC_TRUE;
1445bb05f991SStefano Zampini     pcbddc->use_faces    = PETSC_TRUE;
1446bb05f991SStefano Zampini   }
1447bb05f991SStefano Zampini 
1448f4ddd8eeSStefano Zampini   /* Get stdout for dbg */
144970cf5478SStefano Zampini   if (pcbddc->dbg_flag) {
1450ad540459SPierre Jolivet     if (!pcbddc->dbg_viewer) pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc));
14519566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer));
14529566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIAddTab(pcbddc->dbg_viewer, 2 * pcbddc->current_level));
1453f4ddd8eeSStefano Zampini   }
1454f4ddd8eeSStefano Zampini 
1455c703fcc7SStefano Zampini   /* process topology information */
14569566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Topology[pcbddc->current_level], pc, 0, 0, 0));
145771582508SStefano Zampini   if (pcbddc->recompute_topography) {
14589566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeLocalTopologyInfo(pc));
14591baa6e33SBarry Smith     if (pcbddc->discretegradient) PetscCall(PCBDDCNedelecSupport(pc));
1460c703fcc7SStefano Zampini   }
14614f819b78SStefano Zampini   if (pcbddc->corner_selected) pcbddc->use_vertices = PETSC_TRUE;
1462a13144ffSStefano Zampini 
1463c703fcc7SStefano Zampini   /* change basis if requested by the user */
14645e8657edSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) {
14655e8657edSStefano Zampini     /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */
14665e8657edSStefano Zampini     pcbddc->use_change_of_basis = PETSC_FALSE;
14679566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeLocalMatrix(pc, pcbddc->user_ChangeOfBasisMatrix));
14685e8657edSStefano Zampini   } else {
14699566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcbddc->local_mat));
14709566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)matis->A));
14715e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
1472d16cbb6bSStefano Zampini   }
1473d16cbb6bSStefano Zampini 
14744f1b2e48SStefano Zampini   /*
1475c703fcc7SStefano Zampini      Compute change of basis on local pressures (aka zerodiag dofs) with the benign trick
14764f1b2e48SStefano Zampini      This should come earlier then PCISSetUp for extracting the correct subdomain matrices
14774f1b2e48SStefano Zampini   */
14789566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignShellMat(pc, PETSC_TRUE));
1479d16cbb6bSStefano Zampini   if (pcbddc->benign_saddle_point) {
14809f47a83aSStefano Zampini     PC_IS *pcis = (PC_IS *)pc->data;
14819f47a83aSStefano Zampini 
148205b28244SStefano Zampini     if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE;
14833b03f7bbSStefano Zampini     /* detect local saddle point and change the basis in pcbddc->local_mat */
14849566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignDetectSaddlePoint(pc, (PetscBool)(!pcbddc->recompute_topography), &zerodiag));
1485a3df083aSStefano Zampini     /* pop B0 mat from local mat */
14869566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignPopOrPushB0(pc, PETSC_TRUE));
14871dd7afcfSStefano Zampini     /* give pcis a hint to not reuse submatrices during PCISCreate */
14881dd7afcfSStefano Zampini     if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) {
14891dd7afcfSStefano Zampini       if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) {
14901dd7afcfSStefano Zampini         pcis->reusesubmatrices = PETSC_FALSE;
14911dd7afcfSStefano Zampini       } else {
1492a3df083aSStefano Zampini         pcis->reusesubmatrices = PETSC_TRUE;
14931dd7afcfSStefano Zampini       }
1494a3df083aSStefano Zampini     } else {
14959f47a83aSStefano Zampini       pcis->reusesubmatrices = PETSC_FALSE;
1496674ae819SStefano Zampini     }
1497a3df083aSStefano Zampini   }
149827b6a85dSStefano Zampini 
14998037d520SStefano Zampini   /* propagate relevant information */
1500b94d7dedSBarry Smith   PetscCall(MatIsSymmetricKnown(matis->A, &isset, &issym));
1501b94d7dedSBarry Smith   if (isset) PetscCall(MatSetOption(pcbddc->local_mat, MAT_SYMMETRIC, issym));
1502b94d7dedSBarry Smith   PetscCall(MatIsSPDKnown(matis->A, &isset, &isspd));
1503b94d7dedSBarry Smith   if (isset) PetscCall(MatSetOption(pcbddc->local_mat, MAT_SPD, isspd));
1504e496cd5dSStefano Zampini 
15055e8657edSStefano Zampini   /* Set up all the "iterative substructuring" common block without computing solvers */
15065e8657edSStefano Zampini   {
15075e8657edSStefano Zampini     Mat temp_mat;
15085e8657edSStefano Zampini 
15095e8657edSStefano Zampini     temp_mat = matis->A;
15105e8657edSStefano Zampini     matis->A = pcbddc->local_mat;
15119566063dSJacob Faibussowitsch     PetscCall(PCISSetUp(pc, PETSC_TRUE, PETSC_FALSE));
15125e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
15135e8657edSStefano Zampini     matis->A          = temp_mat;
15145e8657edSStefano Zampini   }
1515684f6988SStefano Zampini 
151681d14e9dSStefano Zampini   /* Analyze interface */
151764ac59b8SStefano Zampini   if (!pcbddc->graphanalyzed) {
15189566063dSJacob Faibussowitsch     PetscCall(PCBDDCAnalyzeInterface(pc));
15198de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
15200fdf79fbSJacob 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");
1521a198735bSStefano Zampini     if (pcbddc->compute_nonetflux) {
1522669cc0f4SStefano Zampini       MatNullSpace nnfnnsp;
1523669cc0f4SStefano Zampini 
152428b400f6SJacob Faibussowitsch       PetscCheck(pcbddc->divudotp, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Missing divudotp operator");
15259566063dSJacob Faibussowitsch       PetscCall(PCBDDCComputeNoNetFlux(pc->pmat, pcbddc->divudotp, pcbddc->divudotp_trans, pcbddc->divudotp_vl2l, pcbddc->mat_graph, &nnfnnsp));
152671582508SStefano Zampini       /* TODO what if a nearnullspace is already attached? */
15278037d520SStefano Zampini       if (nnfnnsp) {
15289566063dSJacob Faibussowitsch         PetscCall(MatSetNearNullSpace(pc->pmat, nnfnnsp));
15299566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceDestroy(&nnfnnsp));
1530669cc0f4SStefano Zampini       }
1531674ae819SStefano Zampini     }
15328037d520SStefano Zampini   }
15339566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Topology[pcbddc->current_level], pc, 0, 0, 0));
1534fb8d54d4SStefano Zampini 
15355408967cSStefano Zampini   /* check existence of a divergence free extension, i.e.
15365408967cSStefano Zampini      b(v_I,p_0) = 0 for all v_I (raise error if not).
15375408967cSStefano Zampini      Also, check that PCBDDCBenignGetOrSetP0 works */
153848a46eb9SPierre Jolivet   if (pcbddc->benign_saddle_point && pcbddc->dbg_flag > 1) PetscCall(PCBDDCBenignCheck(pc, zerodiag));
15399566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&zerodiag));
154006f24817SStefano Zampini 
1541b96c3477SStefano Zampini   /* Setup local dirichlet solver ksp_D and sub_schurs solvers */
154248a46eb9SPierre Jolivet   if (computesubschurs && pcbddc->recompute_topography) PetscCall(PCBDDCInitSubSchurs(pc));
15439d54b7f4SStefano Zampini   /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/
154448a46eb9SPierre Jolivet   if (!pcbddc->use_deluxe_scaling) PetscCall(PCBDDCScalingSetUp(pc));
1545c703fcc7SStefano Zampini 
1546c703fcc7SStefano Zampini   /* finish setup solvers and do adaptive selection of constraints */
1547b334f244SStefano Zampini   sub_schurs = pcbddc->sub_schurs;
1548b334f244SStefano Zampini   if (sub_schurs && sub_schurs->schur_explicit) {
15491baa6e33SBarry Smith     if (computesubschurs) PetscCall(PCBDDCSetUpSubSchurs(pc));
15509566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetUpLocalSolvers(pc, PETSC_TRUE, PETSC_FALSE));
1551d5574798SStefano Zampini   } else {
15529566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetUpLocalSolvers(pc, PETSC_TRUE, PETSC_FALSE));
15531baa6e33SBarry Smith     if (computesubschurs) PetscCall(PCBDDCSetUpSubSchurs(pc));
15542070dbb6SStefano Zampini   }
155508122e43SStefano Zampini   if (pcbddc->adaptive_selection) {
15569566063dSJacob Faibussowitsch     PetscCall(PCBDDCAdaptiveSelection(pc));
15578de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1558b7eb3628SStefano Zampini   }
1559684f6988SStefano Zampini 
1560f4ddd8eeSStefano Zampini   /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */
1561fb8d54d4SStefano Zampini   new_nearnullspace_provided = PETSC_FALSE;
15629566063dSJacob Faibussowitsch   PetscCall(MatGetNearNullSpace(pc->pmat, &nearnullspace));
1563f4ddd8eeSStefano Zampini   if (pcbddc->onearnullspace) { /* already used nearnullspace */
1564f4ddd8eeSStefano Zampini     if (!nearnullspace) {       /* near null space attached to mat has been destroyed */
1565f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1566f4ddd8eeSStefano Zampini     } else {
1567f4ddd8eeSStefano Zampini       /* determine if the two nullspaces are different (should be lightweight) */
1568f4ddd8eeSStefano Zampini       if (nearnullspace != pcbddc->onearnullspace) {
1569f4ddd8eeSStefano Zampini         new_nearnullspace_provided = PETSC_TRUE;
1570165b64e2SStefano Zampini       } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */
1571f4ddd8eeSStefano Zampini         PetscInt         i;
1572165b64e2SStefano Zampini         const Vec       *nearnullvecs;
1573165b64e2SStefano Zampini         PetscObjectState state;
1574165b64e2SStefano Zampini         PetscInt         nnsp_size;
15759566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceGetVecs(nearnullspace, NULL, &nnsp_size, &nearnullvecs));
1576f4ddd8eeSStefano Zampini         for (i = 0; i < nnsp_size; i++) {
15779566063dSJacob Faibussowitsch           PetscCall(PetscObjectStateGet((PetscObject)nearnullvecs[i], &state));
1578165b64e2SStefano Zampini           if (pcbddc->onearnullvecs_state[i] != state) {
1579f4ddd8eeSStefano Zampini             new_nearnullspace_provided = PETSC_TRUE;
1580f4ddd8eeSStefano Zampini             break;
1581f4ddd8eeSStefano Zampini           }
1582f4ddd8eeSStefano Zampini         }
1583f4ddd8eeSStefano Zampini       }
1584f4ddd8eeSStefano Zampini     }
1585f4ddd8eeSStefano Zampini   } else {
1586f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* both nearnullspaces are null */
1587f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_FALSE;
1588f4ddd8eeSStefano Zampini     } else { /* nearnullspace attached later */
1589f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1590f4ddd8eeSStefano Zampini     }
1591f4ddd8eeSStefano Zampini   }
1592f4ddd8eeSStefano Zampini 
1593f4ddd8eeSStefano Zampini   /* Setup constraints and related work vectors */
1594727cdba6SStefano Zampini   /* reset primal space flags */
15959566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_LocalWork[pcbddc->current_level], pc, 0, 0, 0));
1596f4ddd8eeSStefano Zampini   pcbddc->new_primal_space       = PETSC_FALSE;
1597727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_FALSE;
15988de1fae6SStefano Zampini   if (computeconstraintsmatrix || new_nearnullspace_provided) {
1599727cdba6SStefano Zampini     /* It also sets the primal space flags */
16009566063dSJacob Faibussowitsch     PetscCall(PCBDDCConstraintsSetUp(pc));
16019543d0ffSStefano Zampini   }
1602e7b262bdSStefano Zampini   /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */
16039566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetUpLocalWorkVectors(pc));
16045e8657edSStefano Zampini 
16055e8657edSStefano Zampini   if (pcbddc->use_change_of_basis) {
1606*f4f49eeaSPierre Jolivet     PC_IS *pcis = (PC_IS *)pc->data;
16075e8657edSStefano Zampini 
16089566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeLocalMatrix(pc, pcbddc->ChangeOfBasisMatrix));
16094f1b2e48SStefano Zampini     if (pcbddc->benign_change) {
16109566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcbddc->benign_B0));
1611c263805aSStefano Zampini       /* pop B0 from pcbddc->local_mat */
16129566063dSJacob Faibussowitsch       PetscCall(PCBDDCBenignPopOrPushB0(pc, PETSC_TRUE));
1613c263805aSStefano Zampini     }
16145e8657edSStefano Zampini     /* get submatrices */
16159566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_IB));
16169566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_BI));
16179566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_BB));
16189566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_B_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &pcis->A_BB));
16199566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_I_local, pcis->is_B_local, MAT_INITIAL_MATRIX, &pcis->A_IB));
16209566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat, pcis->is_B_local, pcis->is_I_local, MAT_INITIAL_MATRIX, &pcis->A_BI));
16213975b054SStefano Zampini     /* set flag in pcis to not reuse submatrices during PCISCreate */
16223975b054SStefano Zampini     pcis->reusesubmatrices = PETSC_FALSE;
16239c6a02ceSStefano Zampini   } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) {
16249566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcbddc->local_mat));
16259566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)matis->A));
16265e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
16275e8657edSStefano Zampini   }
162835509ce9Sstefano_zampini 
162935509ce9Sstefano_zampini   /* interface pressure block row for B_C */
16309566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lP", (PetscObject *)&lP));
16319566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_lA", (PetscObject *)&lA));
163235509ce9Sstefano_zampini   if (lA && lP) {
163335509ce9Sstefano_zampini     PC_IS    *pcis = (PC_IS *)pc->data;
163435509ce9Sstefano_zampini     Mat       B_BI, B_BB, Bt_BI, Bt_BB;
163535509ce9Sstefano_zampini     PetscBool issym;
1636b94d7dedSBarry Smith 
16379566063dSJacob Faibussowitsch     PetscCall(MatIsSymmetric(lA, PETSC_SMALL, &issym));
16386cc1294bSstefano_zampini     if (issym) {
16399566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_I_local, MAT_INITIAL_MATRIX, &B_BI));
16409566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_B_local, MAT_INITIAL_MATRIX, &B_BB));
16419566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(B_BI, &Bt_BI));
16429566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(B_BB, &Bt_BB));
164335509ce9Sstefano_zampini     } else {
16449566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_I_local, MAT_INITIAL_MATRIX, &B_BI));
16459566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, lP, pcis->is_B_local, MAT_INITIAL_MATRIX, &B_BB));
16469566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, pcis->is_I_local, lP, MAT_INITIAL_MATRIX, &Bt_BI));
16479566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA, pcis->is_B_local, lP, MAT_INITIAL_MATRIX, &Bt_BB));
164835509ce9Sstefano_zampini     }
16499566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_B_BI", (PetscObject)B_BI));
16509566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_B_BB", (PetscObject)B_BB));
16519566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_Bt_BI", (PetscObject)Bt_BI));
16529566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc, "__KSPFETIDP_Bt_BB", (PetscObject)Bt_BB));
16539566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B_BI));
16549566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B_BB));
16559566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Bt_BI));
16569566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Bt_BB));
165735509ce9Sstefano_zampini   }
16589566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_LocalWork[pcbddc->current_level], pc, 0, 0, 0));
165935509ce9Sstefano_zampini 
1660b96c3477SStefano Zampini   /* SetUp coarse and local Neumann solvers */
16619566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetUpSolvers(pc));
1662b96c3477SStefano Zampini   /* SetUp Scaling operator */
16631baa6e33SBarry Smith   if (pcbddc->use_deluxe_scaling) PetscCall(PCBDDCScalingSetUp(pc));
1664c703fcc7SStefano Zampini 
16651dd7afcfSStefano Zampini   /* mark topography as done */
166656282151SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
16670369aaf7SStefano Zampini 
16681dd7afcfSStefano Zampini   /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */
16699566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignShellMat(pc, PETSC_FALSE));
16701dd7afcfSStefano Zampini 
167158a03d70SStefano Zampini   if (pcbddc->dbg_flag) {
16729566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISubtractTab(pcbddc->dbg_viewer, 2 * pcbddc->current_level));
16739566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer));
16742b510759SStefano Zampini   }
16753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16760c7d97c5SJed Brown }
16770c7d97c5SJed Brown 
167866976f2fSJacob Faibussowitsch static PetscErrorCode PCApply_BDDC(PC pc, Vec r, Vec z)
1679d71ae5a4SJacob Faibussowitsch {
1680*f4f49eeaSPierre Jolivet   PC_IS            *pcis   = (PC_IS *)pc->data;
1681*f4f49eeaSPierre Jolivet   PC_BDDC          *pcbddc = (PC_BDDC *)pc->data;
1682b3338236SStefano Zampini   Mat               lA     = NULL;
1683b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
16843b03a366Sstefano_zampini   const PetscScalar one   = 1.0;
16853b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
16862617d88aSStefano Zampini   const PetscScalar zero  = 0.0;
16870c7d97c5SJed Brown   /* This code is similar to that provided in nn.c for PCNN
16880c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
1689b097fa66SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */
16900c7d97c5SJed Brown 
16910c7d97c5SJed Brown   PetscFunctionBegin;
16929566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(citation, &cited));
169348a46eb9SPierre Jolivet   if (pcbddc->switch_static) PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat, &lA));
1694b3338236SStefano Zampini 
16951dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
16961dd7afcfSStefano Zampini     Vec swap;
169727b6a85dSStefano Zampini 
16989566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, r, pcbddc->work_change));
16991dd7afcfSStefano Zampini     swap                = pcbddc->work_change;
17001dd7afcfSStefano Zampini     pcbddc->work_change = r;
17011dd7afcfSStefano Zampini     r                   = swap;
17021dd7afcfSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
17039cc2a9b1Sstefano_zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) {
17049566063dSJacob Faibussowitsch       PetscCall(VecCopy(r, pcis->vec1_global));
17059566063dSJacob Faibussowitsch       PetscCall(VecLockReadPush(pcis->vec1_global));
17061dd7afcfSStefano Zampini     }
17071dd7afcfSStefano Zampini   }
170827b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
17099566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, r, PETSC_TRUE));
1710efc2fbd9SStefano Zampini   }
1711bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET && !pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
17129566063dSJacob Faibussowitsch     PetscCall(VecCopy(r, z));
17130c7d97c5SJed Brown     /* First Dirichlet solve */
17149566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
17159566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
17160c7d97c5SJed Brown     /*
17170c7d97c5SJed Brown       Assembling right hand side for BDDC operator
1718b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
1719674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
17200c7d97c5SJed Brown     */
17219566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
1722a1cb837bSStefano Zampini     if (n_D) {
17239566063dSJacob Faibussowitsch       PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D));
17249566063dSJacob Faibussowitsch       PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
17259566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D));
17269566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec2_D, m_one));
172716909a7fSStefano Zampini       if (pcbddc->switch_static) {
17289566063dSJacob Faibussowitsch         PetscCall(VecSet(pcis->vec1_N, 0.));
17299566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
17309566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
173116909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
17329566063dSJacob Faibussowitsch           PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N));
173316909a7fSStefano Zampini         } else {
17349566063dSJacob Faibussowitsch           PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
17359566063dSJacob Faibussowitsch           PetscCall(MatMult(lA, pcis->vec2_N, pcis->vec1_N));
17369566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
173716909a7fSStefano Zampini         }
17389566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD));
17399566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD));
17409566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
17419566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
174216909a7fSStefano Zampini       } else {
17439566063dSJacob Faibussowitsch         PetscCall(MatMult(pcis->A_BI, pcis->vec2_D, pcis->vec1_B));
174416909a7fSStefano Zampini       }
1745b097fa66SStefano Zampini     } else {
1746a1cb837bSStefano Zampini       PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
17479566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_B, zero));
1748b097fa66SStefano Zampini     }
17499566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE));
17509566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE));
17519566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingRestriction(pc, z, pcis->vec1_B));
1752b76ba322SStefano Zampini   } else {
175348a46eb9SPierre Jolivet     if (!pcbddc->benign_apply_coarse_only) PetscCall(PCBDDCScalingRestriction(pc, r, pcis->vec1_B));
17544fee134fSStefano Zampini   }
1755bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) {
175628b400f6SJacob Faibussowitsch     PetscCheck(pcbddc->switch_static, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "You forgot to pass -pc_bddc_switch_static");
17579566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
17589566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
1759bc960bbfSJed Brown   }
1760b76ba322SStefano Zampini 
17612617d88aSStefano Zampini   /* Apply interface preconditioner
17622617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
17639566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(pc, PETSC_FALSE));
17642617d88aSStefano Zampini 
1765674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
17669566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(pc, pcis->vec1_B, z));
1767bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) {
17689566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_D, z, INSERT_VALUES, SCATTER_REVERSE));
17699566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_D, z, INSERT_VALUES, SCATTER_REVERSE));
17703ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1771bc960bbfSJed Brown   }
17723b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
17739566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
17749566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
1775b097fa66SStefano Zampini   if (n_B) {
177616909a7fSStefano Zampini     if (pcbddc->switch_static) {
17779566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
17789566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
17799566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
17809566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
178116909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
17829566063dSJacob Faibussowitsch         PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N));
178316909a7fSStefano Zampini       } else {
17849566063dSJacob Faibussowitsch         PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
17859566063dSJacob Faibussowitsch         PetscCall(MatMult(lA, pcis->vec2_N, pcis->vec1_N));
17869566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
178716909a7fSStefano Zampini       }
17889566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD));
17899566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD));
179016909a7fSStefano Zampini     } else {
17919566063dSJacob Faibussowitsch       PetscCall(MatMult(pcis->A_IB, pcis->vec1_B, pcis->vec3_D));
179216909a7fSStefano Zampini     }
179316909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
179416909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
17959566063dSJacob Faibussowitsch       PetscCall(MatMult(lA, pcis->vec1_D, pcis->vec3_D));
179616909a7fSStefano Zampini     } else {
17979566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_D, pcis->vec1_N));
17989566063dSJacob Faibussowitsch       PetscCall(MatMult(lA, pcis->vec1_N, pcis->vec2_N));
17999566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec2_N, pcis->vec3_D));
180016909a7fSStefano Zampini     }
1801b097fa66SStefano Zampini   }
18029566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
18039566063dSJacob Faibussowitsch   PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec3_D, pcis->vec4_D));
18049566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
18059566063dSJacob Faibussowitsch   PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec4_D));
1806efc2fbd9SStefano Zampini 
18078ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1808b097fa66SStefano Zampini     if (pcbddc->switch_static) {
18099566063dSJacob Faibussowitsch       PetscCall(VecAXPBYPCZ(pcis->vec2_D, m_one, one, m_one, pcis->vec4_D, pcis->vec1_D));
1810b097fa66SStefano Zampini     } else {
18119566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec2_D, m_one, m_one, pcis->vec4_D));
1812b097fa66SStefano Zampini     }
18139566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE));
18149566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE));
1815b097fa66SStefano Zampini   } else {
1816b097fa66SStefano Zampini     if (pcbddc->switch_static) {
18179566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec4_D, one, m_one, pcis->vec1_D));
1818b097fa66SStefano Zampini     } else {
18199566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec4_D, m_one));
1820b097fa66SStefano Zampini     }
18219566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE));
18229566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE));
1823b097fa66SStefano Zampini   }
182427b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
18251baa6e33SBarry Smith     if (pcbddc->benign_apply_coarse_only) PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n));
18269566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, z, PETSC_FALSE));
1827efc2fbd9SStefano Zampini   }
18281f4df5f7SStefano Zampini 
18291dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1830f913dca9SStefano Zampini     pcbddc->work_change = r;
18319566063dSJacob Faibussowitsch     PetscCall(VecCopy(z, pcbddc->work_change));
18329566063dSJacob Faibussowitsch     PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcbddc->work_change, z));
18331dd7afcfSStefano Zampini   }
18343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18350c7d97c5SJed Brown }
183650efa1b5SStefano Zampini 
183766976f2fSJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_BDDC(PC pc, Vec r, Vec z)
1838d71ae5a4SJacob Faibussowitsch {
1839*f4f49eeaSPierre Jolivet   PC_IS            *pcis   = (PC_IS *)pc->data;
1840*f4f49eeaSPierre Jolivet   PC_BDDC          *pcbddc = (PC_BDDC *)pc->data;
1841b3338236SStefano Zampini   Mat               lA     = NULL;
1842b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
184350efa1b5SStefano Zampini   const PetscScalar one   = 1.0;
184450efa1b5SStefano Zampini   const PetscScalar m_one = -1.0;
184550efa1b5SStefano Zampini   const PetscScalar zero  = 0.0;
184650efa1b5SStefano Zampini 
184750efa1b5SStefano Zampini   PetscFunctionBegin;
18489566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(citation, &cited));
184948a46eb9SPierre Jolivet   if (pcbddc->switch_static) PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat, &lA));
18501dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
18511dd7afcfSStefano Zampini     Vec swap;
185227b6a85dSStefano Zampini 
18539566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, r, pcbddc->work_change));
18541dd7afcfSStefano Zampini     swap                = pcbddc->work_change;
18551dd7afcfSStefano Zampini     pcbddc->work_change = r;
18561dd7afcfSStefano Zampini     r                   = swap;
185727b6a85dSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
18588ae0ca82SStefano Zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->exact_dirichlet_trick_app && pcbddc->change_interior) {
18599566063dSJacob Faibussowitsch       PetscCall(VecCopy(r, pcis->vec1_global));
18609566063dSJacob Faibussowitsch       PetscCall(VecLockReadPush(pcis->vec1_global));
18611dd7afcfSStefano Zampini     }
186227b6a85dSStefano Zampini   }
186327b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
18649566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, r, PETSC_TRUE));
1865537c1cdfSStefano Zampini   }
18668ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
18679566063dSJacob Faibussowitsch     PetscCall(VecCopy(r, z));
186850efa1b5SStefano Zampini     /* First Dirichlet solve */
18699566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
18709566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, r, pcis->vec1_D, INSERT_VALUES, SCATTER_FORWARD));
187150efa1b5SStefano Zampini     /*
187250efa1b5SStefano Zampini       Assembling right hand side for BDDC operator
1873b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
187450efa1b5SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
187550efa1b5SStefano Zampini     */
1876b097fa66SStefano Zampini     if (n_D) {
18779566063dSJacob Faibussowitsch       PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
18789566063dSJacob Faibussowitsch       PetscCall(KSPSolveTranspose(pcbddc->ksp_D, pcis->vec1_D, pcis->vec2_D));
18799566063dSJacob Faibussowitsch       PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
18809566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec2_D));
18819566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec2_D, m_one));
188216909a7fSStefano Zampini       if (pcbddc->switch_static) {
18839566063dSJacob Faibussowitsch         PetscCall(VecSet(pcis->vec1_N, 0.));
18849566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
18859566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
188616909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
18879566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N));
188816909a7fSStefano Zampini         } else {
18899566063dSJacob Faibussowitsch           PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
18909566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(lA, pcis->vec2_N, pcis->vec1_N));
18919566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
189216909a7fSStefano Zampini         }
18939566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD));
18949566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec1_D, ADD_VALUES, SCATTER_FORWARD));
18959566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
18969566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec2_N, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
189716909a7fSStefano Zampini       } else {
18989566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcis->A_IB, pcis->vec2_D, pcis->vec1_B));
189916909a7fSStefano Zampini       }
1900b097fa66SStefano Zampini     } else {
19019566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_B, zero));
1902b097fa66SStefano Zampini     }
19039566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE));
19049566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, z, ADD_VALUES, SCATTER_REVERSE));
19059566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingRestriction(pc, z, pcis->vec1_B));
190650efa1b5SStefano Zampini   } else {
19079566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingRestriction(pc, r, pcis->vec1_B));
190850efa1b5SStefano Zampini   }
190950efa1b5SStefano Zampini 
191050efa1b5SStefano Zampini   /* Apply interface preconditioner
191150efa1b5SStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
19129566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(pc, PETSC_TRUE));
191350efa1b5SStefano Zampini 
191450efa1b5SStefano Zampini   /* Apply transpose of partition of unity operator */
19159566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(pc, pcis->vec1_B, z));
191650efa1b5SStefano Zampini 
191750efa1b5SStefano Zampini   /* Second Dirichlet solve and assembling of output */
19189566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
19199566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, z, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
1920b097fa66SStefano Zampini   if (n_B) {
192116909a7fSStefano Zampini     if (pcbddc->switch_static) {
19229566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
19239566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec1_D, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
19249566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
19259566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec1_B, pcis->vec1_N, INSERT_VALUES, SCATTER_REVERSE));
192616909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
19279566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N));
192816909a7fSStefano Zampini       } else {
19299566063dSJacob Faibussowitsch         PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
19309566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(lA, pcis->vec2_N, pcis->vec1_N));
19319566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec1_N, pcis->vec2_N));
193216909a7fSStefano Zampini       }
19339566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD));
19349566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D, pcis->vec2_N, pcis->vec3_D, INSERT_VALUES, SCATTER_FORWARD));
193516909a7fSStefano Zampini     } else {
19369566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcis->A_BI, pcis->vec1_B, pcis->vec3_D));
193716909a7fSStefano Zampini     }
193816909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
193916909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
19409566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(lA, pcis->vec1_D, pcis->vec3_D));
194116909a7fSStefano Zampini     } else {
19429566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->switch_static_change, pcis->vec1_D, pcis->vec1_N));
19439566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(lA, pcis->vec1_N, pcis->vec2_N));
19449566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->switch_static_change, pcis->vec2_N, pcis->vec3_D));
194516909a7fSStefano Zampini     }
1946b097fa66SStefano Zampini   }
19479566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
19489566063dSJacob Faibussowitsch   PetscCall(KSPSolveTranspose(pcbddc->ksp_D, pcis->vec3_D, pcis->vec4_D));
19499566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], pc, 0, 0, 0));
19509566063dSJacob Faibussowitsch   PetscCall(KSPCheckSolve(pcbddc->ksp_D, pc, pcis->vec4_D));
19518ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1952b097fa66SStefano Zampini     if (pcbddc->switch_static) {
19539566063dSJacob Faibussowitsch       PetscCall(VecAXPBYPCZ(pcis->vec2_D, m_one, one, m_one, pcis->vec4_D, pcis->vec1_D));
1954b097fa66SStefano Zampini     } else {
19559566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec2_D, m_one, m_one, pcis->vec4_D));
1956b097fa66SStefano Zampini     }
19579566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE));
19589566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec2_D, z, INSERT_VALUES, SCATTER_REVERSE));
1959b097fa66SStefano Zampini   } else {
1960b097fa66SStefano Zampini     if (pcbddc->switch_static) {
19619566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec4_D, one, m_one, pcis->vec1_D));
1962b097fa66SStefano Zampini     } else {
19639566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec4_D, m_one));
1964b097fa66SStefano Zampini     }
19659566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE));
19669566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec4_D, z, INSERT_VALUES, SCATTER_REVERSE));
1967b097fa66SStefano Zampini   }
196827b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
19699566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc, z, PETSC_FALSE));
1970537c1cdfSStefano Zampini   }
19711dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1972f913dca9SStefano Zampini     pcbddc->work_change = r;
19739566063dSJacob Faibussowitsch     PetscCall(VecCopy(z, pcbddc->work_change));
19749566063dSJacob Faibussowitsch     PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, pcbddc->work_change, z));
19751dd7afcfSStefano Zampini   }
19763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
197750efa1b5SStefano Zampini }
1978674ae819SStefano Zampini 
197966976f2fSJacob Faibussowitsch static PetscErrorCode PCReset_BDDC(PC pc)
1980d71ae5a4SJacob Faibussowitsch {
1981da1bb401SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
19829326c5c6Sstefano_zampini   PC_IS   *pcis   = (PC_IS *)pc->data;
19839326c5c6Sstefano_zampini   KSP      kspD, kspR, kspC;
1984da1bb401SStefano Zampini 
1985da1bb401SStefano Zampini   PetscFunctionBegin;
1986674ae819SStefano Zampini   /* free BDDC custom data  */
19879566063dSJacob Faibussowitsch   PetscCall(PCBDDCResetCustomization(pc));
1988674ae819SStefano Zampini   /* destroy objects related to topography */
19899566063dSJacob Faibussowitsch   PetscCall(PCBDDCResetTopography(pc));
199034a97f8cSStefano Zampini   /* destroy objects for scaling operator */
19919566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingDestroy(pc));
1992674ae819SStefano Zampini   /* free solvers stuff */
19939566063dSJacob Faibussowitsch   PetscCall(PCBDDCResetSolvers(pc));
199462a6ff1dSStefano Zampini   /* free global vectors needed in presolve */
19959566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->temp_solution));
19969566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->original_rhs));
19971dd7afcfSStefano Zampini   /* free data created by PCIS */
199804c3f3b8SBarry Smith   PetscCall(PCISReset(pc));
19999326c5c6Sstefano_zampini 
20009326c5c6Sstefano_zampini   /* restore defaults */
20019326c5c6Sstefano_zampini   kspD = pcbddc->ksp_D;
20029326c5c6Sstefano_zampini   kspR = pcbddc->ksp_R;
20039326c5c6Sstefano_zampini   kspC = pcbddc->coarse_ksp;
20049566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(pc->data, sizeof(*pcbddc)));
20059326c5c6Sstefano_zampini   pcis->n_neigh                     = -1;
20069326c5c6Sstefano_zampini   pcis->scaling_factor              = 1.0;
20079326c5c6Sstefano_zampini   pcis->reusesubmatrices            = PETSC_TRUE;
20089326c5c6Sstefano_zampini   pcbddc->use_local_adj             = PETSC_TRUE;
20099326c5c6Sstefano_zampini   pcbddc->use_vertices              = PETSC_TRUE;
20109326c5c6Sstefano_zampini   pcbddc->use_edges                 = PETSC_TRUE;
20119326c5c6Sstefano_zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
20129326c5c6Sstefano_zampini   pcbddc->vertex_size               = 1;
20139326c5c6Sstefano_zampini   pcbddc->recompute_topography      = PETSC_TRUE;
20149326c5c6Sstefano_zampini   pcbddc->coarse_size               = -1;
20159326c5c6Sstefano_zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
20169326c5c6Sstefano_zampini   pcbddc->coarsening_ratio          = 8;
20179326c5c6Sstefano_zampini   pcbddc->coarse_eqs_per_proc       = 1;
20189326c5c6Sstefano_zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
20199326c5c6Sstefano_zampini   pcbddc->nedfield                  = -1;
20209326c5c6Sstefano_zampini   pcbddc->nedglobal                 = PETSC_TRUE;
20219326c5c6Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
20229326c5c6Sstefano_zampini   pcbddc->sub_schurs_layers         = -1;
20239326c5c6Sstefano_zampini   pcbddc->ksp_D                     = kspD;
20249326c5c6Sstefano_zampini   pcbddc->ksp_R                     = kspR;
20259326c5c6Sstefano_zampini   pcbddc->coarse_ksp                = kspC;
20263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20279326c5c6Sstefano_zampini }
20289326c5c6Sstefano_zampini 
202966976f2fSJacob Faibussowitsch static PetscErrorCode PCDestroy_BDDC(PC pc)
2030d71ae5a4SJacob Faibussowitsch {
20319326c5c6Sstefano_zampini   PC_BDDC *pcbddc = (PC_BDDC *)pc->data;
20329326c5c6Sstefano_zampini 
20339326c5c6Sstefano_zampini   PetscFunctionBegin;
20349566063dSJacob Faibussowitsch   PetscCall(PCReset_BDDC(pc));
20359566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcbddc->ksp_D));
20369566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcbddc->ksp_R));
20379566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcbddc->coarse_ksp));
20389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDiscreteGradient_C", NULL));
20399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDivergenceMat_C", NULL));
20409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetChangeOfBasisMat_C", NULL));
20419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesLocalIS_C", NULL));
20429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesIS_C", NULL));
204332fe681dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesLocalIS_C", NULL));
204432fe681dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesIS_C", NULL));
20459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetCoarseningRatio_C", NULL));
20469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevel_C", NULL));
20479566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetUseExactDirichlet_C", NULL));
20489566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevels_C", NULL));
20499566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundaries_C", NULL));
20509566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundariesLocal_C", NULL));
20519566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundaries_C", NULL));
20529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundariesLocal_C", NULL));
20539566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundaries_C", NULL));
20549566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundariesLocal_C", NULL));
20559566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundaries_C", NULL));
20569566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundariesLocal_C", NULL));
20579566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplitting_C", NULL));
20589566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplittingLocal_C", NULL));
20599566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", NULL));
20609566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCCreateFETIDPOperators_C", NULL));
20619566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetRHS_C", NULL));
20629566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetSolution_C", NULL));
20639566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", NULL));
20649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", NULL));
20659566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
20663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2067da1bb401SStefano Zampini }
20681e6b0712SBarry Smith 
2069d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetCoordinates_BDDC(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
2070d71ae5a4SJacob Faibussowitsch {
2071ab8c8b98SStefano Zampini   PC_BDDC    *pcbddc    = (PC_BDDC *)pc->data;
2072ab8c8b98SStefano Zampini   PCBDDCGraph mat_graph = pcbddc->mat_graph;
2073ab8c8b98SStefano Zampini 
2074ab8c8b98SStefano Zampini   PetscFunctionBegin;
20759566063dSJacob Faibussowitsch   PetscCall(PetscFree(mat_graph->coords));
20769566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nloc * dim, &mat_graph->coords));
20779566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(mat_graph->coords, coords, nloc * dim));
2078ab8c8b98SStefano Zampini   mat_graph->cnloc = nloc;
2079ab8c8b98SStefano Zampini   mat_graph->cdim  = dim;
2080ab8c8b98SStefano Zampini   mat_graph->cloc  = PETSC_FALSE;
20814f819b78SStefano Zampini   /* flg setup */
20824f819b78SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
20834f819b78SStefano Zampini   pcbddc->corner_selected      = PETSC_FALSE;
20843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2085ab8c8b98SStefano Zampini }
2086ab8c8b98SStefano Zampini 
2087d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCPreSolveChangeRHS_BDDC(PC pc, PetscBool *change)
2088d71ae5a4SJacob Faibussowitsch {
2089a06fd7f2SStefano Zampini   PetscFunctionBegin;
2090a06fd7f2SStefano Zampini   *change = PETSC_TRUE;
20913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2092a06fd7f2SStefano Zampini }
2093a06fd7f2SStefano Zampini 
2094d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
2095d71ae5a4SJacob Faibussowitsch {
2096674ae819SStefano Zampini   FETIDPMat_ctx mat_ctx;
2097266e20e9SStefano Zampini   Vec           work;
20983425bc38SStefano Zampini   PC_IS        *pcis;
20993425bc38SStefano Zampini   PC_BDDC      *pcbddc;
21000c7d97c5SJed Brown 
21013425bc38SStefano Zampini   PetscFunctionBegin;
21029566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx));
21033425bc38SStefano Zampini   pcis   = (PC_IS *)mat_ctx->pc->data;
21043425bc38SStefano Zampini   pcbddc = (PC_BDDC *)mat_ctx->pc->data;
21053425bc38SStefano Zampini 
21069566063dSJacob Faibussowitsch   PetscCall(VecSet(fetidp_flux_rhs, 0.0));
2107229984c5Sstefano_zampini   /* copy rhs since we may change it during PCPreSolve_BDDC */
210848a46eb9SPierre Jolivet   if (!pcbddc->original_rhs) PetscCall(VecDuplicate(pcis->vec1_global, &pcbddc->original_rhs));
21096cc1294bSstefano_zampini   if (mat_ctx->rhs_flip) {
21109566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(pcbddc->original_rhs, standard_rhs, mat_ctx->rhs_flip));
21116cc1294bSstefano_zampini   } else {
21129566063dSJacob Faibussowitsch     PetscCall(VecCopy(standard_rhs, pcbddc->original_rhs));
21136cc1294bSstefano_zampini   }
2114af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
2115229984c5Sstefano_zampini     /* interface pressure rhs */
21169566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->g2g_p, fetidp_flux_rhs, pcbddc->original_rhs, INSERT_VALUES, SCATTER_REVERSE));
21179566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->g2g_p, fetidp_flux_rhs, pcbddc->original_rhs, INSERT_VALUES, SCATTER_REVERSE));
21189566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->g2g_p, standard_rhs, fetidp_flux_rhs, INSERT_VALUES, SCATTER_FORWARD));
21199566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->g2g_p, standard_rhs, fetidp_flux_rhs, INSERT_VALUES, SCATTER_FORWARD));
212048a46eb9SPierre Jolivet     if (!mat_ctx->rhs_flip) PetscCall(VecScale(fetidp_flux_rhs, -1.));
21216cc1294bSstefano_zampini   }
2122c08af4c6SStefano Zampini   /*
2123c08af4c6SStefano Zampini      change of basis for physical rhs if needed
2124c08af4c6SStefano Zampini      It also changes the rhs in case of dirichlet boundaries
2125c08af4c6SStefano Zampini   */
21269566063dSJacob Faibussowitsch   PetscCall(PCPreSolve_BDDC(mat_ctx->pc, NULL, pcbddc->original_rhs, NULL));
2127fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
21289566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix, pcbddc->original_rhs, pcbddc->work_change));
21293738a8e6SStefano Zampini     work = pcbddc->work_change;
2130fc17d649SStefano Zampini   } else {
21313738a8e6SStefano Zampini     work = pcbddc->original_rhs;
2132fc17d649SStefano Zampini   }
21333425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
21349566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_D, work, mat_ctx->temp_solution_D, INSERT_VALUES, SCATTER_FORWARD));
21359566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_D, work, mat_ctx->temp_solution_D, INSERT_VALUES, SCATTER_FORWARD));
2136fb223d50SStefano Zampini   /* scale rhs since it should be unassembled */
2137fb223d50SStefano Zampini   /* TODO use counter scaling? (also below) */
21389566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD));
21399566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD));
2140674ae819SStefano Zampini   /* Apply partition of unity */
21419566063dSJacob Faibussowitsch   PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B, pcis->D, mat_ctx->temp_solution_B));
21429566063dSJacob Faibussowitsch   /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */
21438eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
21443425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
21459566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0));
21469566063dSJacob Faibussowitsch     PetscCall(KSPSolve(pcbddc->ksp_D, mat_ctx->temp_solution_D, pcis->vec1_D));
21479566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0));
2148c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
21499566063dSJacob Faibussowitsch     PetscCall(MatMult(pcis->A_BI, pcis->vec1_D, pcis->vec1_B));
21509566063dSJacob Faibussowitsch     PetscCall(VecAXPY(mat_ctx->temp_solution_B, -1.0, pcis->vec1_B));
21519566063dSJacob Faibussowitsch     PetscCall(VecSet(work, 0.0));
21529566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, mat_ctx->temp_solution_B, work, ADD_VALUES, SCATTER_REVERSE));
21539566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, mat_ctx->temp_solution_B, work, ADD_VALUES, SCATTER_REVERSE));
21549566063dSJacob Faibussowitsch     /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */
21559566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD));
21569566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B, work, mat_ctx->temp_solution_B, INSERT_VALUES, SCATTER_FORWARD));
21579566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B, pcis->D, mat_ctx->temp_solution_B));
21583425bc38SStefano Zampini   }
21593425bc38SStefano Zampini   /* BDDC rhs */
21609566063dSJacob Faibussowitsch   PetscCall(VecCopy(mat_ctx->temp_solution_B, pcis->vec1_B));
21611baa6e33SBarry Smith   if (pcbddc->switch_static) PetscCall(VecCopy(mat_ctx->temp_solution_D, pcis->vec1_D));
21623425bc38SStefano Zampini   /* apply BDDC */
21639566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n));
21649566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc, PETSC_FALSE));
21659566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n));
2166229984c5Sstefano_zampini 
21673425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
21689566063dSJacob Faibussowitsch   PetscCall(MatMult(mat_ctx->B_delta, pcis->vec1_B, mat_ctx->lambda_local));
21699566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(mat_ctx->l2g_lambda, mat_ctx->lambda_local, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD));
21709566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(mat_ctx->l2g_lambda, mat_ctx->lambda_local, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD));
2171229984c5Sstefano_zampini   /* Add contribution to interface pressures */
2172229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
21739566063dSJacob Faibussowitsch     PetscCall(MatMult(mat_ctx->B_BB, pcis->vec1_B, mat_ctx->vP));
21741baa6e33SBarry Smith     if (pcbddc->switch_static) PetscCall(MatMultAdd(mat_ctx->B_BI, pcis->vec1_D, mat_ctx->vP, mat_ctx->vP));
21759566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->l2g_p, mat_ctx->vP, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD));
21769566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->l2g_p, mat_ctx->vP, fetidp_flux_rhs, ADD_VALUES, SCATTER_FORWARD));
2177229984c5Sstefano_zampini   }
21783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21793425bc38SStefano Zampini }
21801e6b0712SBarry Smith 
21813425bc38SStefano Zampini /*@
218298ad52f2SBarry Smith   PCBDDCMatFETIDPGetRHS - Compute the right-hand side for a FETI-DP linear system using the physical right-hand side
21833425bc38SStefano Zampini 
21843425bc38SStefano Zampini   Collective
21853425bc38SStefano Zampini 
21863425bc38SStefano Zampini   Input Parameters:
2187f1580f4eSBarry Smith + fetidp_mat   - the FETI-DP matrix object obtained by a call to `PCBDDCCreateFETIDPOperators()`
21880f202f7eSStefano Zampini - standard_rhs - the right-hand side of the original linear system
21893425bc38SStefano Zampini 
2190f1580f4eSBarry Smith   Output Parameter:
21910f202f7eSStefano Zampini . fetidp_flux_rhs - the right-hand side for the FETI-DP linear system
21923425bc38SStefano Zampini 
21933425bc38SStefano Zampini   Level: developer
21943425bc38SStefano Zampini 
2195562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCCreateFETIDPOperators()`, `PCBDDCMatFETIDPGetSolution()`
21963425bc38SStefano Zampini @*/
2197d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
2198d71ae5a4SJacob Faibussowitsch {
2199674ae819SStefano Zampini   FETIDPMat_ctx mat_ctx;
22003425bc38SStefano Zampini 
22013425bc38SStefano Zampini   PetscFunctionBegin;
2202266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat, MAT_CLASSID, 1);
2203266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_rhs, VEC_CLASSID, 2);
2204266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_rhs, VEC_CLASSID, 3);
22059566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx));
2206cac4c232SBarry Smith   PetscUseMethod(mat_ctx->pc, "PCBDDCMatFETIDPGetRHS_C", (Mat, Vec, Vec), (fetidp_mat, standard_rhs, fetidp_flux_rhs));
22073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22083425bc38SStefano Zampini }
22091e6b0712SBarry Smith 
2210d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
2211d71ae5a4SJacob Faibussowitsch {
2212674ae819SStefano Zampini   FETIDPMat_ctx mat_ctx;
22133425bc38SStefano Zampini   PC_IS        *pcis;
22143425bc38SStefano Zampini   PC_BDDC      *pcbddc;
2215229984c5Sstefano_zampini   Vec           work;
22163425bc38SStefano Zampini 
22173425bc38SStefano Zampini   PetscFunctionBegin;
22189566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx));
22193425bc38SStefano Zampini   pcis   = (PC_IS *)mat_ctx->pc->data;
22203425bc38SStefano Zampini   pcbddc = (PC_BDDC *)mat_ctx->pc->data;
22213425bc38SStefano Zampini 
22223425bc38SStefano Zampini   /* apply B_delta^T */
22239566063dSJacob Faibussowitsch   PetscCall(VecSet(pcis->vec1_B, 0.));
22249566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(mat_ctx->l2g_lambda, fetidp_flux_sol, mat_ctx->lambda_local, INSERT_VALUES, SCATTER_REVERSE));
22259566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(mat_ctx->l2g_lambda, fetidp_flux_sol, mat_ctx->lambda_local, INSERT_VALUES, SCATTER_REVERSE));
22269566063dSJacob Faibussowitsch   PetscCall(MatMultTranspose(mat_ctx->B_delta, mat_ctx->lambda_local, pcis->vec1_B));
2227229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
22289566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->l2g_p, fetidp_flux_sol, mat_ctx->vP, INSERT_VALUES, SCATTER_REVERSE));
22299566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->l2g_p, fetidp_flux_sol, mat_ctx->vP, INSERT_VALUES, SCATTER_REVERSE));
22309566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(mat_ctx->Bt_BB, mat_ctx->vP, pcis->vec1_B, pcis->vec1_B));
2231229984c5Sstefano_zampini   }
2232229984c5Sstefano_zampini 
22333425bc38SStefano Zampini   /* compute rhs for BDDC application */
22349566063dSJacob Faibussowitsch   PetscCall(VecAYPX(pcis->vec1_B, -1.0, mat_ctx->temp_solution_B));
22358eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
22369566063dSJacob Faibussowitsch     PetscCall(VecCopy(mat_ctx->temp_solution_D, pcis->vec1_D));
2237229984c5Sstefano_zampini     if (mat_ctx->l2g_p) {
22389566063dSJacob Faibussowitsch       PetscCall(VecScale(mat_ctx->vP, -1.));
22399566063dSJacob Faibussowitsch       PetscCall(MatMultAdd(mat_ctx->Bt_BI, mat_ctx->vP, pcis->vec1_D, pcis->vec1_D));
22403425bc38SStefano Zampini     }
2241229984c5Sstefano_zampini   }
2242229984c5Sstefano_zampini 
22433425bc38SStefano Zampini   /* apply BDDC */
22449566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->benign_p0, pcbddc->benign_n));
22459566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc, PETSC_FALSE));
2246229984c5Sstefano_zampini 
2247229984c5Sstefano_zampini   /* put values into global vector */
2248af140850Sstefano_zampini   if (pcbddc->ChangeOfBasisMatrix) work = pcbddc->work_change;
2249af140850Sstefano_zampini   else work = standard_sol;
22509566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_B, work, INSERT_VALUES, SCATTER_REVERSE));
22519566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_B, work, INSERT_VALUES, SCATTER_REVERSE));
22528eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
22533425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
22549566063dSJacob Faibussowitsch     PetscCall(MatMult(pcis->A_IB, pcis->vec1_B, pcis->vec1_D));
22559566063dSJacob Faibussowitsch     PetscCall(VecAYPX(pcis->vec1_D, -1.0, mat_ctx->temp_solution_D));
22569566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0));
22579566063dSJacob Faibussowitsch     PetscCall(KSPSolve(pcbddc->ksp_D, pcis->vec1_D, pcis->vec1_D));
22589566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0], mat_ctx->pc, 0, 0, 0));
2259c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
22603425bc38SStefano Zampini   }
2261229984c5Sstefano_zampini 
22629566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_D, pcis->vec1_D, work, INSERT_VALUES, SCATTER_REVERSE));
22639566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_D, pcis->vec1_D, work, INSERT_VALUES, SCATTER_REVERSE));
2264266e20e9SStefano Zampini   /* add p0 solution to final solution */
22659566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignGetOrSetP0(mat_ctx->pc, work, PETSC_FALSE));
22661baa6e33SBarry Smith   if (pcbddc->ChangeOfBasisMatrix) PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix, work, standard_sol));
22679566063dSJacob Faibussowitsch   PetscCall(PCPostSolve_BDDC(mat_ctx->pc, NULL, NULL, standard_sol));
2268af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
22699566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->g2g_p, fetidp_flux_sol, standard_sol, INSERT_VALUES, SCATTER_REVERSE));
22709566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->g2g_p, fetidp_flux_sol, standard_sol, INSERT_VALUES, SCATTER_REVERSE));
2271229984c5Sstefano_zampini   }
22723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22733425bc38SStefano Zampini }
22741e6b0712SBarry Smith 
2275d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_BDDCIPC(PC pc, PetscViewer viewer)
2276d71ae5a4SJacob Faibussowitsch {
22775a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
22785a1e936bSStefano Zampini   PetscBool   isascii;
22795a1e936bSStefano Zampini 
22805a1e936bSStefano Zampini   PetscFunctionBegin;
22819566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
22829566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
228348a46eb9SPierre Jolivet   if (isascii) PetscCall(PetscViewerASCIIPrintf(viewer, "BDDC interface preconditioner\n"));
22849566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushTab(viewer));
22859566063dSJacob Faibussowitsch   PetscCall(PCView(bddcipc_ctx->bddc, viewer));
22869566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopTab(viewer));
22873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22885a1e936bSStefano Zampini }
22895a1e936bSStefano Zampini 
2290d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetUp_BDDCIPC(PC pc)
2291d71ae5a4SJacob Faibussowitsch {
22925a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
22935a1e936bSStefano Zampini   PetscBool   isbddc;
22945a1e936bSStefano Zampini   Vec         vv;
22955a1e936bSStefano Zampini   IS          is;
22965a1e936bSStefano Zampini   PC_IS      *pcis;
22975a1e936bSStefano Zampini 
22985a1e936bSStefano Zampini   PetscFunctionBegin;
22999566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
23009566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)bddcipc_ctx->bddc, PCBDDC, &isbddc));
230128b400f6SJacob Faibussowitsch   PetscCheck(isbddc, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Invalid type %s. Must be of type bddc", ((PetscObject)bddcipc_ctx->bddc)->type_name);
23029566063dSJacob Faibussowitsch   PetscCall(PCSetUp(bddcipc_ctx->bddc));
23035a1e936bSStefano Zampini 
23045a1e936bSStefano Zampini   /* create interface scatter */
2305*f4f49eeaSPierre Jolivet   pcis = (PC_IS *)bddcipc_ctx->bddc->data;
23069566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l));
23079566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(pc->pmat, &vv, NULL));
23089566063dSJacob Faibussowitsch   PetscCall(ISRenumber(pcis->is_B_global, NULL, NULL, &is));
23099566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(vv, is, pcis->vec1_B, NULL, &bddcipc_ctx->g2l));
23109566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
23119566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&vv));
23123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23135a1e936bSStefano Zampini }
23145a1e936bSStefano Zampini 
2315d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_BDDCIPC(PC pc, Vec r, Vec x)
2316d71ae5a4SJacob Faibussowitsch {
23175a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
23185a1e936bSStefano Zampini   PC_IS      *pcis;
23195a1e936bSStefano Zampini   VecScatter  tmps;
23205a1e936bSStefano Zampini 
23215a1e936bSStefano Zampini   PetscFunctionBegin;
23229566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
2323*f4f49eeaSPierre Jolivet   pcis              = (PC_IS *)bddcipc_ctx->bddc->data;
23245a1e936bSStefano Zampini   tmps              = pcis->global_to_B;
23255a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
23269566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc, r, pcis->vec1_B));
23279566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc, PETSC_FALSE));
23289566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc, pcis->vec1_B, x));
23295a1e936bSStefano Zampini   pcis->global_to_B = tmps;
23303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23315a1e936bSStefano Zampini }
23325a1e936bSStefano Zampini 
2333d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApplyTranspose_BDDCIPC(PC pc, Vec r, Vec x)
2334d71ae5a4SJacob Faibussowitsch {
23355a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
23365a1e936bSStefano Zampini   PC_IS      *pcis;
23375a1e936bSStefano Zampini   VecScatter  tmps;
23385a1e936bSStefano Zampini 
23395a1e936bSStefano Zampini   PetscFunctionBegin;
23409566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
2341*f4f49eeaSPierre Jolivet   pcis              = (PC_IS *)bddcipc_ctx->bddc->data;
23425a1e936bSStefano Zampini   tmps              = pcis->global_to_B;
23435a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
23449566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc, r, pcis->vec1_B));
23459566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc, PETSC_TRUE));
23469566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc, pcis->vec1_B, x));
23475a1e936bSStefano Zampini   pcis->global_to_B = tmps;
23483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23495a1e936bSStefano Zampini }
23505a1e936bSStefano Zampini 
2351d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_BDDCIPC(PC pc)
2352d71ae5a4SJacob Faibussowitsch {
23535a1e936bSStefano Zampini   BDDCIPC_ctx bddcipc_ctx;
23545a1e936bSStefano Zampini 
23555a1e936bSStefano Zampini   PetscFunctionBegin;
23569566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc, &bddcipc_ctx));
23579566063dSJacob Faibussowitsch   PetscCall(PCDestroy(&bddcipc_ctx->bddc));
23589566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l));
23599566063dSJacob Faibussowitsch   PetscCall(PetscFree(bddcipc_ctx));
23603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23615a1e936bSStefano Zampini }
23625a1e936bSStefano Zampini 
23633425bc38SStefano Zampini /*@
23640f202f7eSStefano Zampini   PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system
23653425bc38SStefano Zampini 
23663425bc38SStefano Zampini   Collective
23673425bc38SStefano Zampini 
23683425bc38SStefano Zampini   Input Parameters:
236920f4b53cSBarry Smith + fetidp_mat      - the FETI-DP matrix obtained by a call to `PCBDDCCreateFETIDPOperators()`
2370f1580f4eSBarry Smith - fetidp_flux_sol - the solution of the FETI-DP linear system`
23713425bc38SStefano Zampini 
2372f1580f4eSBarry Smith   Output Parameter:
23730f202f7eSStefano Zampini . standard_sol - the solution defined on the physical domain
23743425bc38SStefano Zampini 
23753425bc38SStefano Zampini   Level: developer
23763425bc38SStefano Zampini 
2377562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCCreateFETIDPOperators()`, `PCBDDCMatFETIDPGetRHS()`
23783425bc38SStefano Zampini @*/
2379d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
2380d71ae5a4SJacob Faibussowitsch {
2381674ae819SStefano Zampini   FETIDPMat_ctx mat_ctx;
23823425bc38SStefano Zampini 
23833425bc38SStefano Zampini   PetscFunctionBegin;
2384266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat, MAT_CLASSID, 1);
2385266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_sol, VEC_CLASSID, 2);
2386266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_sol, VEC_CLASSID, 3);
23879566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat, &mat_ctx));
2388cac4c232SBarry Smith   PetscUseMethod(mat_ctx->pc, "PCBDDCMatFETIDPGetSolution_C", (Mat, Vec, Vec), (fetidp_mat, fetidp_flux_sol, standard_sol));
23893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23903425bc38SStefano Zampini }
23911e6b0712SBarry Smith 
2392d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc)
2393d71ae5a4SJacob Faibussowitsch {
2394674ae819SStefano Zampini   FETIDPMat_ctx fetidpmat_ctx;
23953425bc38SStefano Zampini   Mat           newmat;
2396674ae819SStefano Zampini   FETIDPPC_ctx  fetidppc_ctx;
23973425bc38SStefano Zampini   PC            newpc;
2398ce94432eSBarry Smith   MPI_Comm      comm;
23993425bc38SStefano Zampini 
24003425bc38SStefano Zampini   PetscFunctionBegin;
24019566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)pc, &comm));
240215579a77SStefano Zampini   /* FETI-DP matrix */
24039566063dSJacob Faibussowitsch   PetscCall(PCBDDCCreateFETIDPMatContext(pc, &fetidpmat_ctx));
24041720468bSStefano Zampini   fetidpmat_ctx->fully_redundant = fully_redundant;
24059566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetupFETIDPMatContext(fetidpmat_ctx));
24069566063dSJacob Faibussowitsch   PetscCall(MatCreateShell(comm, fetidpmat_ctx->n, fetidpmat_ctx->n, fetidpmat_ctx->N, fetidpmat_ctx->N, fetidpmat_ctx, &newmat));
24079566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)newmat, !fetidpmat_ctx->l2g_lambda_only ? "F" : "G"));
24089566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(newmat, MATOP_MULT, (void (*)(void))FETIDPMatMult));
24099566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(newmat, MATOP_MULT_TRANSPOSE, (void (*)(void))FETIDPMatMultTranspose));
24109566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(newmat, MATOP_DESTROY, (void (*)(void))PCBDDCDestroyFETIDPMat));
241115579a77SStefano Zampini   /* propagate MatOptions */
241215579a77SStefano Zampini   {
241315579a77SStefano Zampini     PC_BDDC  *pcbddc = (PC_BDDC *)fetidpmat_ctx->pc->data;
2414b94d7dedSBarry Smith     PetscBool isset, issym;
241515579a77SStefano Zampini 
2416b94d7dedSBarry Smith     PetscCall(MatIsSymmetricKnown(pc->mat, &isset, &issym));
2417b94d7dedSBarry Smith     if ((isset && issym) || pcbddc->symmetric_primal) PetscCall(MatSetOption(newmat, MAT_SYMMETRIC, PETSC_TRUE));
241815579a77SStefano Zampini   }
24199566063dSJacob Faibussowitsch   PetscCall(MatSetOptionsPrefix(newmat, prefix));
24209566063dSJacob Faibussowitsch   PetscCall(MatAppendOptionsPrefix(newmat, "fetidp_"));
24219566063dSJacob Faibussowitsch   PetscCall(MatSetUp(newmat));
242215579a77SStefano Zampini   /* FETI-DP preconditioner */
24239566063dSJacob Faibussowitsch   PetscCall(PCBDDCCreateFETIDPPCContext(pc, &fetidppc_ctx));
24249566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetupFETIDPPCContext(newmat, fetidppc_ctx));
24259566063dSJacob Faibussowitsch   PetscCall(PCCreate(comm, &newpc));
24269566063dSJacob Faibussowitsch   PetscCall(PCSetOperators(newpc, newmat, newmat));
24279566063dSJacob Faibussowitsch   PetscCall(PCSetOptionsPrefix(newpc, prefix));
24289566063dSJacob Faibussowitsch   PetscCall(PCAppendOptionsPrefix(newpc, "fetidp_"));
24299566063dSJacob Faibussowitsch   PetscCall(PCSetErrorIfFailure(newpc, pc->erroriffailure));
243015579a77SStefano Zampini   if (!fetidpmat_ctx->l2g_lambda_only) { /* standard FETI-DP */
24319566063dSJacob Faibussowitsch     PetscCall(PCSetType(newpc, PCSHELL));
24329566063dSJacob Faibussowitsch     PetscCall(PCShellSetName(newpc, "FETI-DP multipliers"));
24339566063dSJacob Faibussowitsch     PetscCall(PCShellSetContext(newpc, fetidppc_ctx));
24349566063dSJacob Faibussowitsch     PetscCall(PCShellSetApply(newpc, FETIDPPCApply));
24359566063dSJacob Faibussowitsch     PetscCall(PCShellSetApplyTranspose(newpc, FETIDPPCApplyTranspose));
24369566063dSJacob Faibussowitsch     PetscCall(PCShellSetView(newpc, FETIDPPCView));
24379566063dSJacob Faibussowitsch     PetscCall(PCShellSetDestroy(newpc, PCBDDCDestroyFETIDPPC));
24385a1e936bSStefano Zampini   } else { /* saddle-point FETI-DP */
24395a1e936bSStefano Zampini     Mat       M;
24405a1e936bSStefano Zampini     PetscInt  psize;
24415a1e936bSStefano Zampini     PetscBool fake = PETSC_FALSE, isfieldsplit;
2442e1214c54Sstefano_zampini 
24439566063dSJacob Faibussowitsch     PetscCall(ISViewFromOptions(fetidpmat_ctx->lagrange, NULL, "-lag_view"));
24449566063dSJacob Faibussowitsch     PetscCall(ISViewFromOptions(fetidpmat_ctx->pressure, NULL, "-press_view"));
24459566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_PPmat", (PetscObject *)&M));
24469566063dSJacob Faibussowitsch     PetscCall(PCSetType(newpc, PCFIELDSPLIT));
24479566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetIS(newpc, "lag", fetidpmat_ctx->lagrange));
24489566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetIS(newpc, "p", fetidpmat_ctx->pressure));
24499566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetType(newpc, PC_COMPOSITE_SCHUR));
24509566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetSchurFactType(newpc, PC_FIELDSPLIT_SCHUR_FACT_DIAG));
24519566063dSJacob Faibussowitsch     PetscCall(ISGetSize(fetidpmat_ctx->pressure, &psize));
24525a1e936bSStefano Zampini     if (psize != M->rmap->N) {
24535a1e936bSStefano Zampini       Mat      M2;
24545a1e936bSStefano Zampini       PetscInt lpsize;
24555a1e936bSStefano Zampini 
24565a1e936bSStefano Zampini       fake = PETSC_TRUE;
24579566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(fetidpmat_ctx->pressure, &lpsize));
24589566063dSJacob Faibussowitsch       PetscCall(MatCreate(comm, &M2));
24599566063dSJacob Faibussowitsch       PetscCall(MatSetType(M2, MATAIJ));
24609566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(M2, lpsize, lpsize, psize, psize));
24619566063dSJacob Faibussowitsch       PetscCall(MatSetUp(M2));
24629566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(M2, MAT_FINAL_ASSEMBLY));
24639566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(M2, MAT_FINAL_ASSEMBLY));
24649566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSetSchurPre(newpc, PC_FIELDSPLIT_SCHUR_PRE_USER, M2));
24659566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&M2));
24665a1e936bSStefano Zampini     } else {
24679566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSetSchurPre(newpc, PC_FIELDSPLIT_SCHUR_PRE_USER, M));
24685a1e936bSStefano Zampini     }
24699566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetSchurScale(newpc, 1.0));
247015579a77SStefano Zampini 
247115579a77SStefano Zampini     /* we need to setfromoptions and setup here to access the blocks */
24729566063dSJacob Faibussowitsch     PetscCall(PCSetFromOptions(newpc));
24739566063dSJacob Faibussowitsch     PetscCall(PCSetUp(newpc));
2474e1214c54Sstefano_zampini 
24755a1e936bSStefano Zampini     /* user may have changed the type (e.g. -fetidp_pc_type none) */
24769566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)newpc, PCFIELDSPLIT, &isfieldsplit));
24775a1e936bSStefano Zampini     if (isfieldsplit) {
24785a1e936bSStefano Zampini       KSP      *ksps;
24795a1e936bSStefano Zampini       PC        ppc, lagpc;
24805a1e936bSStefano Zampini       PetscInt  nn;
2481064a4176SStefano Zampini       PetscBool ismatis, matisok = PETSC_FALSE, check = PETSC_FALSE;
24825a1e936bSStefano Zampini 
2483e1214c54Sstefano_zampini       /* set the solver for the (0,0) block */
24849566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSchurGetSubKSP(newpc, &nn, &ksps));
24855a1e936bSStefano Zampini       if (!nn) { /* not of type PC_COMPOSITE_SCHUR */
24869566063dSJacob Faibussowitsch         PetscCall(PCFieldSplitGetSubKSP(newpc, &nn, &ksps));
24875a1e936bSStefano Zampini         if (!fake) { /* pass pmat to the pressure solver */
24885a1e936bSStefano Zampini           Mat F;
24895a1e936bSStefano Zampini 
24909566063dSJacob Faibussowitsch           PetscCall(KSPGetOperators(ksps[1], &F, NULL));
24919566063dSJacob Faibussowitsch           PetscCall(KSPSetOperators(ksps[1], F, M));
24925a1e936bSStefano Zampini         }
24935a1e936bSStefano Zampini       } else {
2494b94d7dedSBarry Smith         PetscBool issym, isset;
24955a1e936bSStefano Zampini         Mat       S;
24965a1e936bSStefano Zampini 
24979566063dSJacob Faibussowitsch         PetscCall(PCFieldSplitSchurGetS(newpc, &S));
2498b94d7dedSBarry Smith         PetscCall(MatIsSymmetricKnown(newmat, &isset, &issym));
2499b94d7dedSBarry Smith         if (isset) PetscCall(MatSetOption(S, MAT_SYMMETRIC, issym));
25005a1e936bSStefano Zampini       }
25019566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksps[0], &lagpc));
25029566063dSJacob Faibussowitsch       PetscCall(PCSetType(lagpc, PCSHELL));
25039566063dSJacob Faibussowitsch       PetscCall(PCShellSetName(lagpc, "FETI-DP multipliers"));
25049566063dSJacob Faibussowitsch       PetscCall(PCShellSetContext(lagpc, fetidppc_ctx));
25059566063dSJacob Faibussowitsch       PetscCall(PCShellSetApply(lagpc, FETIDPPCApply));
25069566063dSJacob Faibussowitsch       PetscCall(PCShellSetApplyTranspose(lagpc, FETIDPPCApplyTranspose));
25079566063dSJacob Faibussowitsch       PetscCall(PCShellSetView(lagpc, FETIDPPCView));
25089566063dSJacob Faibussowitsch       PetscCall(PCShellSetDestroy(lagpc, PCBDDCDestroyFETIDPPC));
25095a1e936bSStefano Zampini 
25105a1e936bSStefano Zampini       /* Olof's idea: interface Schur complement preconditioner for the mass matrix */
25119566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksps[1], &ppc));
25125a1e936bSStefano Zampini       if (fake) {
25135a1e936bSStefano Zampini         BDDCIPC_ctx    bddcipc_ctx;
2514ff11fd76SStefano Zampini         PetscContainer c;
25155a1e936bSStefano Zampini 
25165a1e936bSStefano Zampini         matisok = PETSC_TRUE;
25175a1e936bSStefano Zampini 
25185a1e936bSStefano Zampini         /* create inner BDDC solver */
25199566063dSJacob Faibussowitsch         PetscCall(PetscNew(&bddcipc_ctx));
25209566063dSJacob Faibussowitsch         PetscCall(PCCreate(comm, &bddcipc_ctx->bddc));
25219566063dSJacob Faibussowitsch         PetscCall(PCSetType(bddcipc_ctx->bddc, PCBDDC));
25229566063dSJacob Faibussowitsch         PetscCall(PCSetOperators(bddcipc_ctx->bddc, M, M));
25239566063dSJacob Faibussowitsch         PetscCall(PetscObjectQuery((PetscObject)pc, "__KSPFETIDP_pCSR", (PetscObject *)&c));
25249566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)M, MATIS, &ismatis));
2525ff11fd76SStefano Zampini         if (c && ismatis) {
2526ff11fd76SStefano Zampini           Mat       lM;
2527ff11fd76SStefano Zampini           PetscInt *csr, n;
2528ff11fd76SStefano Zampini 
25299566063dSJacob Faibussowitsch           PetscCall(MatISGetLocalMat(M, &lM));
25309566063dSJacob Faibussowitsch           PetscCall(MatGetSize(lM, &n, NULL));
25319566063dSJacob Faibussowitsch           PetscCall(PetscContainerGetPointer(c, (void **)&csr));
25329566063dSJacob Faibussowitsch           PetscCall(PCBDDCSetLocalAdjacencyGraph(bddcipc_ctx->bddc, n, csr, csr + (n + 1), PETSC_COPY_VALUES));
25339566063dSJacob Faibussowitsch           PetscCall(MatISRestoreLocalMat(M, &lM));
2534ff11fd76SStefano Zampini         }
25359566063dSJacob Faibussowitsch         PetscCall(PCSetOptionsPrefix(bddcipc_ctx->bddc, ((PetscObject)ksps[1])->prefix));
25369566063dSJacob Faibussowitsch         PetscCall(PCSetErrorIfFailure(bddcipc_ctx->bddc, pc->erroriffailure));
25379566063dSJacob Faibussowitsch         PetscCall(PCSetFromOptions(bddcipc_ctx->bddc));
25385a1e936bSStefano Zampini 
25395a1e936bSStefano Zampini         /* wrap the interface application */
25409566063dSJacob Faibussowitsch         PetscCall(PCSetType(ppc, PCSHELL));
25419566063dSJacob Faibussowitsch         PetscCall(PCShellSetName(ppc, "FETI-DP pressure"));
25429566063dSJacob Faibussowitsch         PetscCall(PCShellSetContext(ppc, bddcipc_ctx));
25439566063dSJacob Faibussowitsch         PetscCall(PCShellSetSetUp(ppc, PCSetUp_BDDCIPC));
25449566063dSJacob Faibussowitsch         PetscCall(PCShellSetApply(ppc, PCApply_BDDCIPC));
25459566063dSJacob Faibussowitsch         PetscCall(PCShellSetApplyTranspose(ppc, PCApplyTranspose_BDDCIPC));
25469566063dSJacob Faibussowitsch         PetscCall(PCShellSetView(ppc, PCView_BDDCIPC));
25479566063dSJacob Faibussowitsch         PetscCall(PCShellSetDestroy(ppc, PCDestroy_BDDCIPC));
25485a1e936bSStefano Zampini       }
25495a1e936bSStefano Zampini 
25505a1e936bSStefano Zampini       /* determine if we need to assemble M to construct a preconditioner */
25515a1e936bSStefano Zampini       if (!matisok) {
25529566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)M, MATIS, &ismatis));
25539566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompareAny((PetscObject)ppc, &matisok, PCBDDC, PCJACOBI, PCNONE, PCMG, ""));
255448a46eb9SPierre Jolivet         if (ismatis && !matisok) PetscCall(MatConvert(M, MATAIJ, MAT_INPLACE_MATRIX, &M));
25555a1e936bSStefano Zampini       }
2556064a4176SStefano Zampini 
2557064a4176SStefano Zampini       /* run the subproblems to check convergence */
25589566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)newmat)->prefix, "-check_saddlepoint", &check, NULL));
2559064a4176SStefano Zampini       if (check) {
2560064a4176SStefano Zampini         PetscInt i;
2561064a4176SStefano Zampini 
2562064a4176SStefano Zampini         for (i = 0; i < nn; i++) {
2563064a4176SStefano Zampini           KSP       kspC;
2564e8f11ae9SBarry Smith           PC        npc;
2565064a4176SStefano Zampini           Mat       F, pF;
2566064a4176SStefano Zampini           Vec       x, y;
2567064a4176SStefano Zampini           PetscBool isschur, prec = PETSC_TRUE;
2568064a4176SStefano Zampini 
25699566063dSJacob Faibussowitsch           PetscCall(KSPCreate(PetscObjectComm((PetscObject)ksps[i]), &kspC));
25703821be0aSBarry Smith           PetscCall(KSPSetNestLevel(kspC, pc->kspnestlevel));
25719566063dSJacob Faibussowitsch           PetscCall(KSPSetOptionsPrefix(kspC, ((PetscObject)ksps[i])->prefix));
25729566063dSJacob Faibussowitsch           PetscCall(KSPAppendOptionsPrefix(kspC, "check_"));
25739566063dSJacob Faibussowitsch           PetscCall(KSPGetOperators(ksps[i], &F, &pF));
25749566063dSJacob Faibussowitsch           PetscCall(PetscObjectTypeCompare((PetscObject)F, MATSCHURCOMPLEMENT, &isschur));
2575064a4176SStefano Zampini           if (isschur) {
2576064a4176SStefano Zampini             KSP  kspS, kspS2;
2577064a4176SStefano Zampini             Mat  A00, pA00, A10, A01, A11;
2578064a4176SStefano Zampini             char prefix[256];
2579064a4176SStefano Zampini 
25809566063dSJacob Faibussowitsch             PetscCall(MatSchurComplementGetKSP(F, &kspS));
25819566063dSJacob Faibussowitsch             PetscCall(MatSchurComplementGetSubMatrices(F, &A00, &pA00, &A01, &A10, &A11));
25829566063dSJacob Faibussowitsch             PetscCall(MatCreateSchurComplement(A00, pA00, A01, A10, A11, &F));
25839566063dSJacob Faibussowitsch             PetscCall(MatSchurComplementGetKSP(F, &kspS2));
25849566063dSJacob Faibussowitsch             PetscCall(PetscSNPrintf(prefix, sizeof(prefix), "%sschur_", ((PetscObject)kspC)->prefix));
25859566063dSJacob Faibussowitsch             PetscCall(KSPSetOptionsPrefix(kspS2, prefix));
2586e8f11ae9SBarry Smith             PetscCall(KSPGetPC(kspS2, &npc));
2587e8f11ae9SBarry Smith             PetscCall(PCSetType(npc, PCKSP));
2588e8f11ae9SBarry Smith             PetscCall(PCKSPSetKSP(npc, kspS));
25899566063dSJacob Faibussowitsch             PetscCall(KSPSetFromOptions(kspS2));
2590e8f11ae9SBarry Smith             PetscCall(KSPGetPC(kspS2, &npc));
2591e8f11ae9SBarry Smith             PetscCall(PCSetUseAmat(npc, PETSC_TRUE));
2592064a4176SStefano Zampini           } else {
25939566063dSJacob Faibussowitsch             PetscCall(PetscObjectReference((PetscObject)F));
2594064a4176SStefano Zampini           }
25959566063dSJacob Faibussowitsch           PetscCall(KSPSetFromOptions(kspC));
25969566063dSJacob Faibussowitsch           PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)kspC)->prefix, "-preconditioned", &prec, NULL));
2597064a4176SStefano Zampini           if (prec) {
2598e8f11ae9SBarry Smith             PetscCall(KSPGetPC(ksps[i], &npc));
2599e8f11ae9SBarry Smith             PetscCall(KSPSetPC(kspC, npc));
2600064a4176SStefano Zampini           }
26019566063dSJacob Faibussowitsch           PetscCall(KSPSetOperators(kspC, F, pF));
26029566063dSJacob Faibussowitsch           PetscCall(MatCreateVecs(F, &x, &y));
26039566063dSJacob Faibussowitsch           PetscCall(VecSetRandom(x, NULL));
26049566063dSJacob Faibussowitsch           PetscCall(MatMult(F, x, y));
26059566063dSJacob Faibussowitsch           PetscCall(KSPSolve(kspC, y, x));
2606e8f11ae9SBarry Smith           PetscCall(KSPCheckSolve(kspC, npc, x));
26079566063dSJacob Faibussowitsch           PetscCall(KSPDestroy(&kspC));
26089566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&F));
26099566063dSJacob Faibussowitsch           PetscCall(VecDestroy(&x));
26109566063dSJacob Faibussowitsch           PetscCall(VecDestroy(&y));
2611064a4176SStefano Zampini         }
2612064a4176SStefano Zampini       }
26139566063dSJacob Faibussowitsch       PetscCall(PetscFree(ksps));
2614e1214c54Sstefano_zampini     }
26155a1e936bSStefano Zampini   }
26163425bc38SStefano Zampini   /* return pointers for objects created */
26173425bc38SStefano Zampini   *fetidp_mat = newmat;
26183425bc38SStefano Zampini   *fetidp_pc  = newpc;
26193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26203425bc38SStefano Zampini }
26211e6b0712SBarry Smith 
262294ef8ddeSSatish Balay /*@C
26230f202f7eSStefano Zampini   PCBDDCCreateFETIDPOperators - Create FETI-DP operators
26243425bc38SStefano Zampini 
26253425bc38SStefano Zampini   Collective
26263425bc38SStefano Zampini 
26273425bc38SStefano Zampini   Input Parameters:
262898ad52f2SBarry Smith + pc              - the `PCBDDC` preconditioning context (setup should have been called before)
2629547c9a8eSstefano_zampini . fully_redundant - true for a fully redundant set of Lagrange multipliers
263020f4b53cSBarry Smith - prefix          - optional options database prefix for the objects to be created (can be `NULL`)
263128509bceSStefano Zampini 
263228509bceSStefano Zampini   Output Parameters:
26330f202f7eSStefano Zampini + fetidp_mat - shell FETI-DP matrix object
26340f202f7eSStefano Zampini - fetidp_pc  - shell Dirichlet preconditioner for FETI-DP matrix
263528509bceSStefano Zampini 
26363425bc38SStefano Zampini   Level: developer
26373425bc38SStefano Zampini 
2638f1580f4eSBarry Smith   Note:
2639f1580f4eSBarry Smith   Currently the only operations provided for FETI-DP matrix are `MatMult()` and `MatMultTranspose()`
26403425bc38SStefano Zampini 
2641562efe2eSBarry Smith .seealso: [](ch_ksp), `PCBDDC`, `PCBDDCMatFETIDPGetRHS()`, `PCBDDCMatFETIDPGetSolution()`
26423425bc38SStefano Zampini @*/
2643d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc)
2644d71ae5a4SJacob Faibussowitsch {
26453425bc38SStefano Zampini   PetscFunctionBegin;
26463425bc38SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
26470fdf79fbSJacob Faibussowitsch   PetscCheck(pc->setupcalled, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "You must call PCSetup_BDDC() first");
2648cac4c232SBarry Smith   PetscUseMethod(pc, "PCBDDCCreateFETIDPOperators_C", (PC, PetscBool, const char *, Mat *, PC *), (pc, fully_redundant, prefix, fetidp_mat, fetidp_pc));
26493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26503425bc38SStefano Zampini }
2651f1580f4eSBarry Smith 
2652da1bb401SStefano Zampini /*MC
26531d27aa22SBarry Smith    PCBDDC - Balancing Domain Decomposition by Constraints preconditioners, {cite}`dohrmann2007approximate`, {cite}`klawonn2006dual`, {cite}`mandel2008multispace`
26540c7d97c5SJed Brown 
2655f1580f4eSBarry Smith    Requires `MATIS` matrices (Pmat) with local matrices (inside the `MATIS`) of type `MATSEQAIJ`, `MATSEQBAIJ` or `MATSEQSBAIJ`
265628509bceSStefano Zampini 
265728509bceSStefano Zampini    It also works with unsymmetric and indefinite problems.
265828509bceSStefano Zampini 
2659f1580f4eSBarry Smith    Unlike 'conventional' interface preconditioners, `PCBDDC` iterates over all degrees of freedom, not just those on the interface. This allows the use
2660f1580f4eSBarry Smith    of approximate solvers on the subdomains.
2661b6fdb6dfSStefano Zampini 
26621d27aa22SBarry Smith    Approximate local solvers are automatically adapted (see {cite}`dohrmann2007approximate`,) if the user has attached a nullspace object to the subdomain matrices, and informed
2663f1580f4eSBarry Smith    `PCBDDC` of using approximate solvers (via the command line).
266428509bceSStefano Zampini 
2665f1580f4eSBarry Smith    Boundary nodes are split in vertices, edges and faces classes using information from the local to global mapping of dofs and the local connectivity graph of nodes.
2666f1580f4eSBarry Smith    The latter can be customized by using `PCBDDCSetLocalAdjacencyGraph()`
266728509bceSStefano Zampini 
2668f1580f4eSBarry Smith    Additional information on dofs can be provided by using `PCBDDCSetDofsSplitting()`, `PCBDDCSetDirichletBoundaries()`, `PCBDDCSetNeumannBoundaries()`, and
2669f1580f4eSBarry Smith    `PCBDDCSetPrimalVerticesIS()` and their local counterparts.
267028509bceSStefano Zampini 
2671f1580f4eSBarry Smith    Constraints can be customized by attaching a `MatNullSpace` object to the `MATIS` matrix via `MatSetNearNullSpace()`. Non-singular modes are retained via SVD.
267228509bceSStefano Zampini 
26731d27aa22SBarry Smith    Change of basis is performed similarly to {cite}`klawonn2006dual` when requested. When more than one constraint is present on a single connected component
2674f1580f4eSBarry Smith    (i.e. an edge or a face), a robust method based on local QR factorizations is used.
2675f1580f4eSBarry Smith    User defined change of basis can be passed to `PCBDDC` with `PCBDDCSetChangeOfBasisMat()`
267628509bceSStefano Zampini 
26771d27aa22SBarry Smith    The PETSc implementation also supports multilevel `PCBDDC` {cite}`mandel2008multispace`. Coarse grids are partitioned using a `MatPartitioning` object.
267828509bceSStefano Zampini 
26791d27aa22SBarry Smith    Adaptive selection of primal constraints is supported for SPD systems with high-contrast in the coefficients if MUMPS or MKL_PARDISO are present.
2680f1580f4eSBarry Smith    Future versions of the code will also consider using PASTIX.
26810f202f7eSStefano Zampini 
2682f1580f4eSBarry Smith    An experimental interface to the FETI-DP method is available. FETI-DP operators could be created using `PCBDDCCreateFETIDPOperators()`.
2683f1580f4eSBarry Smith     A stand-alone class for the FETI-DP method will be provided in the next releases.
26840f202f7eSStefano Zampini 
2685f1580f4eSBarry Smith    Options Database Keys:
2686a2b725a8SWilliam Gropp +    -pc_bddc_use_vertices <true>         - use or not vertices in primal space
26870f202f7eSStefano Zampini .    -pc_bddc_use_edges <true>            - use or not edges in primal space
26880f202f7eSStefano Zampini .    -pc_bddc_use_faces <false>           - use or not faces in primal space
26890f202f7eSStefano Zampini .    -pc_bddc_symmetric <true>            - symmetric computation of primal basis functions. Specify false for unsymmetric problems
26900f202f7eSStefano Zampini .    -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only)
26910f202f7eSStefano Zampini .    -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested
26920f202f7eSStefano Zampini .    -pc_bddc_switch_static <false>       - switches from M_2 (default) to M_3 operator (see reference article [1])
269328509bceSStefano Zampini .    -pc_bddc_levels <0>                  - maximum number of levels for multilevel
26940f202f7eSStefano 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)
26955459c157SBarry 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)
26960f202f7eSStefano Zampini .    -pc_bddc_use_deluxe_scaling <false>  - use deluxe scaling
269771f2caa7Sprj- .    -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)
2698bd2a564bSStefano 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)
269928509bceSStefano Zampini -    -pc_bddc_check_level <0>             - set verbosity level of debugging output
270028509bceSStefano Zampini 
2701f1580f4eSBarry Smith    Options for Dirichlet, Neumann or coarse solver can be set using the appropriate options prefix
270228509bceSStefano Zampini .vb
270328509bceSStefano Zampini       -pc_bddc_dirichlet_
270428509bceSStefano Zampini       -pc_bddc_neumann_
270528509bceSStefano Zampini       -pc_bddc_coarse_
270628509bceSStefano Zampini .ve
2707f1580f4eSBarry Smith    e.g. -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. `PCBDDC` uses by default `KSPPREONLY` and `PCLU`.
270828509bceSStefano Zampini 
2709f1580f4eSBarry Smith    When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified using the options prefix
271028509bceSStefano Zampini .vb
2711312be037SStefano Zampini       -pc_bddc_dirichlet_lN_
2712312be037SStefano Zampini       -pc_bddc_neumann_lN_
2713312be037SStefano Zampini       -pc_bddc_coarse_lN_
271428509bceSStefano Zampini .ve
27150f202f7eSStefano Zampini    Note that level number ranges from the finest (0) to the coarsest (N).
2716f1580f4eSBarry 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
2717f1580f4eSBarry Smith    to the option, e.g.
27180f202f7eSStefano Zampini .vb
27190f202f7eSStefano Zampini      -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3
27200f202f7eSStefano Zampini .ve
27210f202f7eSStefano 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
2722da1bb401SStefano Zampini 
2723da1bb401SStefano Zampini    Level: intermediate
2724da1bb401SStefano Zampini 
27251d27aa22SBarry Smith    Contributed by:
27261d27aa22SBarry Smith    Stefano Zampini
2727da1bb401SStefano Zampini 
2728562efe2eSBarry Smith .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `MATIS`, `PCLU`, `PCGAMG`, `PC`, `PCBDDCSetLocalAdjacencyGraph()`, `PCBDDCSetDofsSplitting()`,
2729f1580f4eSBarry Smith           `PCBDDCSetDirichletBoundaries()`, `PCBDDCSetNeumannBoundaries()`, `PCBDDCSetPrimalVerticesIS()`, `MatNullSpace`, `MatSetNearNullSpace()`,
2730f1580f4eSBarry Smith           `PCBDDCSetChangeOfBasisMat()`, `PCBDDCCreateFETIDPOperators()`, `PCNN`
2731da1bb401SStefano Zampini M*/
2732b2573a8aSBarry Smith 
2733d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
2734d71ae5a4SJacob Faibussowitsch {
2735da1bb401SStefano Zampini   PC_BDDC *pcbddc;
2736da1bb401SStefano Zampini 
2737da1bb401SStefano Zampini   PetscFunctionBegin;
27384dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&pcbddc));
27393ec1f749SStefano Zampini   pc->data = pcbddc;
2740da1bb401SStefano Zampini 
274104c3f3b8SBarry Smith   PetscCall(PCISInitialize(pc));
2742da1bb401SStefano Zampini 
27439326c5c6Sstefano_zampini   /* create local graph structure */
27449566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphCreate(&pcbddc->mat_graph));
27459326c5c6Sstefano_zampini 
27469326c5c6Sstefano_zampini   /* BDDC nonzero defaults */
27476d9e27e4SStefano Zampini   pcbddc->use_nnsp                  = PETSC_TRUE;
274808a5cf49SStefano Zampini   pcbddc->use_local_adj             = PETSC_TRUE;
274947d04d0dSStefano Zampini   pcbddc->use_vertices              = PETSC_TRUE;
275047d04d0dSStefano Zampini   pcbddc->use_edges                 = PETSC_TRUE;
27513301b35fSStefano Zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
275214f95afaSStefano Zampini   pcbddc->vertex_size               = 1;
2753c703fcc7SStefano Zampini   pcbddc->recompute_topography      = PETSC_TRUE;
275468457ee5SStefano Zampini   pcbddc->coarse_size               = -1;
275585c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
275647d04d0dSStefano Zampini   pcbddc->coarsening_ratio          = 8;
275757de7509SStefano Zampini   pcbddc->coarse_eqs_per_proc       = 1;
275827b6a85dSStefano Zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
27591e0482f5SStefano Zampini   pcbddc->nedfield                  = -1;
27601e0482f5SStefano Zampini   pcbddc->nedglobal                 = PETSC_TRUE;
2761be12c134Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
2762b96c3477SStefano Zampini   pcbddc->sub_schurs_layers         = -1;
2763bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[0]     = 0.0;
2764bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[1]     = 0.0;
2765b7eb3628SStefano Zampini 
2766da1bb401SStefano Zampini   /* function pointers */
2767da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
276893bd9ae7SStefano Zampini   pc->ops->applytranspose      = PCApplyTranspose_BDDC;
2769da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
2770da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
2771da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
27726b78500eSPatrick Sanan   pc->ops->view                = PCView_BDDC;
27730a545947SLisandro Dalcin   pc->ops->applyrichardson     = NULL;
27740a545947SLisandro Dalcin   pc->ops->applysymmetricleft  = NULL;
27750a545947SLisandro Dalcin   pc->ops->applysymmetricright = NULL;
2776534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
2777534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
27789326c5c6Sstefano_zampini   pc->ops->reset               = PCReset_BDDC;
2779da1bb401SStefano Zampini 
2780da1bb401SStefano Zampini   /* composing function */
27819566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDiscreteGradient_C", PCBDDCSetDiscreteGradient_BDDC));
27829566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDivergenceMat_C", PCBDDCSetDivergenceMat_BDDC));
27839566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetChangeOfBasisMat_C", PCBDDCSetChangeOfBasisMat_BDDC));
27849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesLocalIS_C", PCBDDCSetPrimalVerticesLocalIS_BDDC));
27859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetPrimalVerticesIS_C", PCBDDCSetPrimalVerticesIS_BDDC));
27869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesLocalIS_C", PCBDDCGetPrimalVerticesLocalIS_BDDC));
27879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetPrimalVerticesIS_C", PCBDDCGetPrimalVerticesIS_BDDC));
27889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetCoarseningRatio_C", PCBDDCSetCoarseningRatio_BDDC));
27899566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevel_C", PCBDDCSetLevel_BDDC));
27909566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetUseExactDirichlet_C", PCBDDCSetUseExactDirichlet_BDDC));
27919566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLevels_C", PCBDDCSetLevels_BDDC));
27929566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundaries_C", PCBDDCSetDirichletBoundaries_BDDC));
27939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDirichletBoundariesLocal_C", PCBDDCSetDirichletBoundariesLocal_BDDC));
27949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundaries_C", PCBDDCSetNeumannBoundaries_BDDC));
27959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetNeumannBoundariesLocal_C", PCBDDCSetNeumannBoundariesLocal_BDDC));
27969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundaries_C", PCBDDCGetDirichletBoundaries_BDDC));
27979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetDirichletBoundariesLocal_C", PCBDDCGetDirichletBoundariesLocal_BDDC));
27989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundaries_C", PCBDDCGetNeumannBoundaries_BDDC));
27999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCGetNeumannBoundariesLocal_C", PCBDDCGetNeumannBoundariesLocal_BDDC));
28009566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplitting_C", PCBDDCSetDofsSplitting_BDDC));
28019566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetDofsSplittingLocal_C", PCBDDCSetDofsSplittingLocal_BDDC));
28029566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCSetLocalAdjacencyGraph_C", PCBDDCSetLocalAdjacencyGraph_BDDC));
28039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCCreateFETIDPOperators_C", PCBDDCCreateFETIDPOperators_BDDC));
28049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetRHS_C", PCBDDCMatFETIDPGetRHS_BDDC));
28059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCBDDCMatFETIDPGetSolution_C", PCBDDCMatFETIDPGetSolution_BDDC));
28069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCPreSolveChangeRHS_C", PCPreSolveChangeRHS_BDDC));
28079566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_BDDC));
28083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2809da1bb401SStefano Zampini }
281043371fb9SStefano Zampini 
281143371fb9SStefano Zampini /*@C
2812f1580f4eSBarry Smith   PCBDDCInitializePackage - This function initializes everything in the `PCBDDC` package. It is called
2813f1580f4eSBarry Smith   from `PCInitializePackage()`.
281443371fb9SStefano Zampini 
281543371fb9SStefano Zampini   Level: developer
281643371fb9SStefano Zampini 
2817562efe2eSBarry Smith .seealso: [](ch_ksp), `PetscInitialize()`, `PCBDDCFinalizePackage()`
281843371fb9SStefano Zampini @*/
2819d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCInitializePackage(void)
2820d71ae5a4SJacob Faibussowitsch {
282143371fb9SStefano Zampini   int i;
282243371fb9SStefano Zampini 
282343371fb9SStefano Zampini   PetscFunctionBegin;
28243ba16761SJacob Faibussowitsch   if (PCBDDCPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS);
282543371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_TRUE;
28269566063dSJacob Faibussowitsch   PetscCall(PetscRegisterFinalize(PCBDDCFinalizePackage));
282743371fb9SStefano Zampini 
282843371fb9SStefano Zampini   /* general events */
28299566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCTopo", PC_CLASSID, &PC_BDDC_Topology[0]));
28309566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCLKSP", PC_CLASSID, &PC_BDDC_LocalSolvers[0]));
28319566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCLWor", PC_CLASSID, &PC_BDDC_LocalWork[0]));
28329566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCorr", PC_CLASSID, &PC_BDDC_CorrectionSetUp[0]));
28339566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCASet", PC_CLASSID, &PC_BDDC_ApproxSetUp[0]));
28349566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCAApp", PC_CLASSID, &PC_BDDC_ApproxApply[0]));
28359566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCSet", PC_CLASSID, &PC_BDDC_CoarseSetUp[0]));
28369566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCKSP", PC_CLASSID, &PC_BDDC_CoarseSolver[0]));
28379566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCAdap", PC_CLASSID, &PC_BDDC_AdaptiveSetUp[0]));
28389566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCScal", PC_CLASSID, &PC_BDDC_Scaling[0]));
28399566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCSchr", PC_CLASSID, &PC_BDDC_Schurs[0]));
28409566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCDirS", PC_CLASSID, &PC_BDDC_Solves[0][0]));
28419566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCNeuS", PC_CLASSID, &PC_BDDC_Solves[0][1]));
28429566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCoaS", PC_CLASSID, &PC_BDDC_Solves[0][2]));
284343371fb9SStefano Zampini   for (i = 1; i < PETSC_PCBDDC_MAXLEVELS; i++) {
284443371fb9SStefano Zampini     char ename[32];
284543371fb9SStefano Zampini 
28469566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCTopo l%02d", i));
28479566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Topology[i]));
28489566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCLKSP l%02d", i));
28499566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_LocalSolvers[i]));
28509566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCLWor l%02d", i));
28519566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_LocalWork[i]));
28529566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCorr l%02d", i));
28539566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CorrectionSetUp[i]));
28549566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCASet l%02d", i));
28559566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_ApproxSetUp[i]));
28569566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCAApp l%02d", i));
28579566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_ApproxApply[i]));
28589566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCSet l%02d", i));
28599566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CoarseSetUp[i]));
28609566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCKSP l%02d", i));
28619566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_CoarseSolver[i]));
28629566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCAdap l%02d", i));
28639566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_AdaptiveSetUp[i]));
28649566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCScal l%02d", i));
28659566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Scaling[i]));
28669566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCSchr l%02d", i));
28679566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Schurs[i]));
28689566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCDirS l%02d", i));
28699566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][0]));
28709566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCNeuS l%02d", i));
28719566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][1]));
28729566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename, sizeof(ename), "PCBDDCCoaS l%02d", i));
28739566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename, PC_CLASSID, &PC_BDDC_Solves[i][2]));
287443371fb9SStefano Zampini   }
28753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
287643371fb9SStefano Zampini }
287743371fb9SStefano Zampini 
287843371fb9SStefano Zampini /*@C
2879f1580f4eSBarry Smith   PCBDDCFinalizePackage - This function frees everything from the `PCBDDC` package. It is
2880f1580f4eSBarry Smith   called from `PetscFinalize()` automatically.
288143371fb9SStefano Zampini 
288243371fb9SStefano Zampini   Level: developer
288343371fb9SStefano Zampini 
2884562efe2eSBarry Smith .seealso: [](ch_ksp), `PetscFinalize()`, `PCBDDCInitializePackage()`
288543371fb9SStefano Zampini @*/
2886d71ae5a4SJacob Faibussowitsch PetscErrorCode PCBDDCFinalizePackage(void)
2887d71ae5a4SJacob Faibussowitsch {
288843371fb9SStefano Zampini   PetscFunctionBegin;
288943371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_FALSE;
28903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
289143371fb9SStefano Zampini }
2892