xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision b94d7ded0a05f1bbd5e48daa6f92b28259c75b44)
153cdbc3dSStefano Zampini /* TODOLIST
2eb97c9d2SStefano Zampini 
3eb97c9d2SStefano Zampini    Solvers
4a0d3c3abSStefano Zampini    - Add support for cholesky for coarse solver (similar to local solvers)
5eb97c9d2SStefano Zampini    - Propagate ksp prefixes for solvers to mat objects?
6eb97c9d2SStefano Zampini 
7eb97c9d2SStefano Zampini    User interface
80f202f7eSStefano Zampini    - ** DM attached to pc?
9eb97c9d2SStefano Zampini 
10eb97c9d2SStefano Zampini    Debugging output
11b9b85e73SStefano Zampini    - * Better management of verbosity levels of debugging output
12eb97c9d2SStefano Zampini 
13eb97c9d2SStefano Zampini    Extra
14b9b85e73SStefano Zampini    - *** Is it possible to work with PCBDDCGraph on boundary indices only (less memory consumed)?
15eb97c9d2SStefano Zampini    - BDDC with MG framework?
16eb97c9d2SStefano Zampini 
17eb97c9d2SStefano Zampini    MATIS related operations contained in BDDC code
18eb97c9d2SStefano Zampini    - Provide general case for subassembling
19eb97c9d2SStefano Zampini 
2053cdbc3dSStefano Zampini */
210c7d97c5SJed Brown 
225e5bbd0aSStefano Zampini #include <petsc/private/pcbddcimpl.h> /*I "petscpc.h" I*/  /* includes for fortran wrappers */
235e5bbd0aSStefano Zampini #include <petsc/private/pcbddcprivateimpl.h>
243b03a366Sstefano_zampini #include <petscblaslapack.h>
25674ae819SStefano Zampini 
2643371fb9SStefano Zampini static PetscBool PCBDDCPackageInitialized = PETSC_FALSE;
2743371fb9SStefano Zampini 
28f3d41395Sstefano_zampini static PetscBool  cited = PETSC_FALSE;
29f3d41395Sstefano_zampini static const char citation[] =
30f3d41395Sstefano_zampini "@article{ZampiniPCBDDC,\n"
31f3d41395Sstefano_zampini "author = {Stefano Zampini},\n"
32f3d41395Sstefano_zampini "title = {{PCBDDC}: A Class of Robust Dual-Primal Methods in {PETS}c},\n"
33f3d41395Sstefano_zampini "journal = {SIAM Journal on Scientific Computing},\n"
34f3d41395Sstefano_zampini "volume = {38},\n"
35f3d41395Sstefano_zampini "number = {5},\n"
36f3d41395Sstefano_zampini "pages = {S282-S306},\n"
37f3d41395Sstefano_zampini "year = {2016},\n"
38f3d41395Sstefano_zampini "doi = {10.1137/15M1025785},\n"
39f3d41395Sstefano_zampini "URL = {http://dx.doi.org/10.1137/15M1025785},\n"
40f3d41395Sstefano_zampini "eprint = {http://dx.doi.org/10.1137/15M1025785}\n"
41f3d41395Sstefano_zampini "}\n";
42f3d41395Sstefano_zampini 
4343371fb9SStefano Zampini PetscLogEvent PC_BDDC_Topology[PETSC_PCBDDC_MAXLEVELS];
4443371fb9SStefano Zampini PetscLogEvent PC_BDDC_LocalSolvers[PETSC_PCBDDC_MAXLEVELS];
4543371fb9SStefano Zampini PetscLogEvent PC_BDDC_LocalWork[PETSC_PCBDDC_MAXLEVELS];
4643371fb9SStefano Zampini PetscLogEvent PC_BDDC_CorrectionSetUp[PETSC_PCBDDC_MAXLEVELS];
478ead10e4SStefano Zampini PetscLogEvent PC_BDDC_ApproxSetUp[PETSC_PCBDDC_MAXLEVELS];
488ead10e4SStefano Zampini PetscLogEvent PC_BDDC_ApproxApply[PETSC_PCBDDC_MAXLEVELS];
4943371fb9SStefano Zampini PetscLogEvent PC_BDDC_CoarseSetUp[PETSC_PCBDDC_MAXLEVELS];
5043371fb9SStefano Zampini PetscLogEvent PC_BDDC_CoarseSolver[PETSC_PCBDDC_MAXLEVELS];
5143371fb9SStefano Zampini PetscLogEvent PC_BDDC_AdaptiveSetUp[PETSC_PCBDDC_MAXLEVELS];
5243371fb9SStefano Zampini PetscLogEvent PC_BDDC_Scaling[PETSC_PCBDDC_MAXLEVELS];
5343371fb9SStefano Zampini PetscLogEvent PC_BDDC_Schurs[PETSC_PCBDDC_MAXLEVELS];
5455c176c0SStefano Zampini PetscLogEvent PC_BDDC_Solves[PETSC_PCBDDC_MAXLEVELS][3];
5543371fb9SStefano Zampini 
56bc960bbfSJed Brown const char *const PCBDDCInterfaceExtTypes[] = {"DIRICHLET","LUMP","PCBDDCInterfaceExtType","PC_BDDC_INTERFACE_EXT_",NULL};
57bc960bbfSJed Brown 
580369aaf7SStefano Zampini PetscErrorCode PCApply_BDDC(PC,Vec,Vec);
590369aaf7SStefano Zampini 
604416b707SBarry Smith PetscErrorCode PCSetFromOptions_BDDC(PetscOptionItems *PetscOptionsObject,PC pc)
610c7d97c5SJed Brown {
620c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
63e569e4e1SStefano Zampini   PetscInt       nt,i;
640c7d97c5SJed Brown 
650c7d97c5SJed Brown   PetscFunctionBegin;
66d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject,"BDDC options");
678eeda7d8SStefano Zampini   /* Verbose debugging */
689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_check_level","Verbose output for PCBDDC (intended for debug)","none",pcbddc->dbg_flag,&pcbddc->dbg_flag,NULL));
69a13144ffSStefano Zampini   /* Approximate solvers */
709566063dSJacob 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));
71bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET) {
729566063dSJacob 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));
739566063dSJacob 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));
74bc960bbfSJed Brown   } else {
75bc960bbfSJed Brown     /* This flag is needed/implied by lumping */
76bc960bbfSJed Brown     pcbddc->switch_static = PETSC_TRUE;
77bc960bbfSJed Brown   }
789566063dSJacob 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));
799566063dSJacob 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));
806b78500eSPatrick Sanan   /* Primal space customization */
819566063dSJacob 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));
829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_graph_maxcount","Maximum number of shared subdomains for a connected component","none",pcbddc->graphmaxcount,&pcbddc->graphmaxcount,NULL));
839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_corner_selection","Activates face-based corner selection","none",pcbddc->corner_selection,&pcbddc->corner_selection,NULL));
849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_vertices","Use or not corner dofs in coarse space","none",pcbddc->use_vertices,&pcbddc->use_vertices,NULL));
859566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_edges","Use or not edge constraints in coarse space","none",pcbddc->use_edges,&pcbddc->use_edges,NULL));
869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_faces","Use or not face constraints in coarse space","none",pcbddc->use_faces,&pcbddc->use_faces,NULL));
879566063dSJacob 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));
889566063dSJacob 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));
899566063dSJacob 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));
909566063dSJacob 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));
918eeda7d8SStefano Zampini   /* Change of basis */
929566063dSJacob 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));
939566063dSJacob 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));
94674ae819SStefano Zampini   if (!pcbddc->use_change_of_basis) {
95674ae819SStefano Zampini     pcbddc->use_change_on_faces = PETSC_FALSE;
96674ae819SStefano Zampini   }
978eeda7d8SStefano Zampini   /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */
989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_switch_static","Switch on static condensation ops around the interface preconditioner","none",pcbddc->switch_static,&pcbddc->switch_static,NULL));
999566063dSJacob 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));
100e569e4e1SStefano Zampini   i    = pcbddc->coarsening_ratio;
1019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","PCBDDCSetCoarseningRatio",i,&i,NULL));
1029566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetCoarseningRatio(pc,i));
103e569e4e1SStefano Zampini   i    = pcbddc->max_levels;
1049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_levels","Set maximum number of levels for multilevel","PCBDDCSetLevels",i,&i,NULL));
1059566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetLevels(pc,i));
1069566063dSJacob 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));
1079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_coarse_estimates","Use estimated eigenvalues for coarse problem","none",pcbddc->use_coarse_estimates,&pcbddc->use_coarse_estimates,NULL));
1089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_use_deluxe_scaling","Use deluxe scaling for BDDC","none",pcbddc->use_deluxe_scaling,&pcbddc->use_deluxe_scaling,NULL));
1099566063dSJacob 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));
1109566063dSJacob 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));
1119566063dSJacob 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));
1129566063dSJacob 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));
1139566063dSJacob 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));
1149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_deluxe_singlemat","Collapse deluxe operators","none",pcbddc->deluxe_singlemat,&pcbddc->deluxe_singlemat,NULL));
1159566063dSJacob 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));
116bd2a564bSStefano Zampini   nt   = 2;
1179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsRealArray("-pc_bddc_adaptive_threshold","Thresholds to be used for adaptive selection of constraints","none",pcbddc->adaptive_threshold,&nt,NULL));
118bd2a564bSStefano Zampini   if (nt == 1) pcbddc->adaptive_threshold[1] = pcbddc->adaptive_threshold[0];
1199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_adaptive_nmin","Minimum number of constraints per connected components","none",pcbddc->adaptive_nmin,&pcbddc->adaptive_nmin,NULL));
1209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-pc_bddc_adaptive_nmax","Maximum number of constraints per connected components","none",pcbddc->adaptive_nmax,&pcbddc->adaptive_nmax,NULL));
1219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_symmetric","Symmetric computation of primal basis functions","none",pcbddc->symmetric_primal,&pcbddc->symmetric_primal,NULL));
1229566063dSJacob 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));
1239566063dSJacob 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));
1249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_benign_change","Compute the pressure change of basis explicitly","none",pcbddc->benign_change_explicit,&pcbddc->benign_change_explicit,NULL));
1259566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_benign_compute_correction","Compute the benign correction during PreSolve","none",pcbddc->benign_compute_correction,&pcbddc->benign_compute_correction,NULL));
1269566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_nonetflux","Automatic computation of no-net-flux quadrature weights","none",pcbddc->compute_nonetflux,&pcbddc->compute_nonetflux,NULL));
1279566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-pc_bddc_detect_disconnected","Detects disconnected subdomains","none",pcbddc->detect_disconnected,&pcbddc->detect_disconnected,NULL));
1289566063dSJacob 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));
1299566063dSJacob 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));
130d0609cedSBarry Smith   PetscOptionsHeadEnd();
1310c7d97c5SJed Brown   PetscFunctionReturn(0);
1320c7d97c5SJed Brown }
1336b78500eSPatrick Sanan 
1346b78500eSPatrick Sanan static PetscErrorCode PCView_BDDC(PC pc,PetscViewer viewer)
1356b78500eSPatrick Sanan {
1366b78500eSPatrick Sanan   PC_BDDC              *pcbddc = (PC_BDDC*)pc->data;
137e9627c49SStefano Zampini   PC_IS                *pcis = (PC_IS*)pc->data;
13871783a16SStefano Zampini   PetscBool            isascii;
139e9627c49SStefano Zampini   PetscSubcomm         subcomm;
140e9627c49SStefano Zampini   PetscViewer          subviewer;
1416b78500eSPatrick Sanan 
1426b78500eSPatrick Sanan   PetscFunctionBegin;
1439566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
1446b78500eSPatrick Sanan   /* ASCII viewer */
1456b78500eSPatrick Sanan   if (isascii) {
1464b2aedd3SStefano Zampini     PetscMPIInt   color,rank,size;
147fbad9177SStefano Zampini     PetscInt64    loc[7],gsum[6],gmax[6],gmin[6],totbenign;
148e9627c49SStefano Zampini     PetscScalar   interface_size;
149e9627c49SStefano Zampini     PetscReal     ratio1=0.,ratio2=0.;
150e9627c49SStefano Zampini     Vec           counter;
1516b78500eSPatrick Sanan 
152b74ba07aSstefano_zampini     if (!pc->setupcalled) {
1539566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"  Partial information available: preconditioner has not been setup yet\n"));
154b74ba07aSstefano_zampini     }
15563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Use verbose output: %" PetscInt_FMT "\n",pcbddc->dbg_flag));
1569566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Use user-defined CSR: %d\n",!!pcbddc->mat_graph->nvtxs_csr));
1579566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Use local mat graph: %d\n",pcbddc->use_local_adj && !pcbddc->mat_graph->nvtxs_csr));
158e9627c49SStefano Zampini     if (pcbddc->mat_graph->twodim) {
1599566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"  Connectivity graph topological dimension: 2\n"));
160e9627c49SStefano Zampini     } else {
1619566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"  Connectivity graph topological dimension: 3\n"));
162e9627c49SStefano Zampini     }
163aefa1729SStefano Zampini     if (pcbddc->graphmaxcount != PETSC_MAX_INT) {
16463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"  Graph max count: %" PetscInt_FMT "\n",pcbddc->graphmaxcount));
165aefa1729SStefano Zampini     }
1669566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Corner selection: %d (selected %d)\n",pcbddc->corner_selection,pcbddc->corner_selected));
16763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Use vertices: %d (vertex size %" PetscInt_FMT ")\n",pcbddc->use_vertices,pcbddc->vertex_size));
1689566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Use edges: %d\n",pcbddc->use_edges));
1699566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Use faces: %d\n",pcbddc->use_faces));
1709566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Use true near null space: %d\n",pcbddc->use_nnsp_true));
1719566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Use QR for single constraints on cc: %d\n",pcbddc->use_qr_single));
1729566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Use change of basis on local edge nodes: %d\n",pcbddc->use_change_of_basis));
1739566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Use change of basis on local face nodes: %d\n",pcbddc->use_change_on_faces));
1749566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  User defined change of basis matrix: %d\n",!!pcbddc->user_ChangeOfBasisMatrix));
1759566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Has change of basis matrix: %d\n",!!pcbddc->ChangeOfBasisMatrix));
1769566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Eliminate dirichlet boundary dofs: %d\n",pcbddc->eliminate_dirdofs));
1779566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Switch on static condensation ops around the interface preconditioner: %d\n",pcbddc->switch_static));
1789566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Use exact dirichlet trick: %d\n",pcbddc->use_exact_dirichlet_trick));
1799566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Interface extension: %s\n",PCBDDCInterfaceExtTypes[pcbddc->interface_extension]));
18063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Multilevel max levels: %" PetscInt_FMT "\n",pcbddc->max_levels));
18163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Multilevel coarsening ratio: %" PetscInt_FMT "\n",pcbddc->coarsening_ratio));
1829566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Use estimated eigs for coarse problem: %d\n",pcbddc->use_coarse_estimates));
1839566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Use deluxe scaling: %d\n",pcbddc->use_deluxe_scaling));
1849566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Use deluxe zerorows: %d\n",pcbddc->deluxe_zerorows));
1859566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Use deluxe singlemat: %d\n",pcbddc->deluxe_singlemat));
1869566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Rebuild interface graph for Schur principal minors: %d\n",pcbddc->sub_schurs_rebuild));
18763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Number of dofs' layers for the computation of principal minors: %" PetscInt_FMT "\n",pcbddc->sub_schurs_layers));
1889566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Use user CSR graph to compute successive layers: %d\n",pcbddc->sub_schurs_use_useradj));
189bd2a564bSStefano Zampini     if (pcbddc->adaptive_threshold[1] != pcbddc->adaptive_threshold[0]) {
19063a3b9bcSJacob 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]));
191bd2a564bSStefano Zampini     } else {
19263a3b9bcSJacob 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]));
193bd2a564bSStefano Zampini     }
19463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Min constraints / connected component: %" PetscInt_FMT "\n",pcbddc->adaptive_nmin));
19563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Max constraints / connected component: %" PetscInt_FMT "\n",pcbddc->adaptive_nmax));
1969566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Invert exact Schur complement for adaptive selection: %d\n",pcbddc->sub_schurs_exact_schur));
1979566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Symmetric computation of primal basis functions: %d\n",pcbddc->symmetric_primal));
19863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Num. Procs. to map coarse adjacency list: %" PetscInt_FMT "\n",pcbddc->coarse_adj_red));
19963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Coarse eqs per proc (significant at the coarsest level): %" PetscInt_FMT "\n",pcbddc->coarse_eqs_per_proc));
2009566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Detect disconnected: %d (filter %d)\n",pcbddc->detect_disconnected,pcbddc->detect_disconnected_filter));
2019566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Benign subspace trick: %d (change explicit %d)\n",pcbddc->benign_saddle_point,pcbddc->benign_change_explicit));
2029566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Benign subspace trick is active: %d\n",pcbddc->benign_have_null));
2039566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Algebraic computation of no-net-flux: %d\n",pcbddc->compute_nonetflux));
204b74ba07aSstefano_zampini     if (!pc->setupcalled) PetscFunctionReturn(0);
2056b78500eSPatrick Sanan 
206fbad9177SStefano Zampini     /* compute interface size */
2079566063dSJacob Faibussowitsch     PetscCall(VecSet(pcis->vec1_B,1.0));
2089566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(pc->pmat,&counter,NULL));
2099566063dSJacob Faibussowitsch     PetscCall(VecSet(counter,0.0));
2109566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE));
2119566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE));
2129566063dSJacob Faibussowitsch     PetscCall(VecSum(counter,&interface_size));
2139566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&counter));
214fbad9177SStefano Zampini 
215fbad9177SStefano Zampini     /* compute some statistics on the domain decomposition */
216e9627c49SStefano Zampini     gsum[0] = 1;
217fbad9177SStefano Zampini     gsum[1] = gsum[2] = gsum[3] = gsum[4] = gsum[5] = 0;
218e9627c49SStefano Zampini     loc[0]  = !!pcis->n;
219e9627c49SStefano Zampini     loc[1]  = pcis->n - pcis->n_B;
220e9627c49SStefano Zampini     loc[2]  = pcis->n_B;
221e9627c49SStefano Zampini     loc[3]  = pcbddc->local_primal_size;
222345ecf6cSStefano Zampini     loc[4]  = pcis->n;
223fbad9177SStefano Zampini     loc[5]  = pcbddc->n_local_subs > 0 ? pcbddc->n_local_subs : (pcis->n ? 1 : 0);
224fbad9177SStefano Zampini     loc[6]  = pcbddc->benign_n;
2259566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(loc,gsum,6,MPIU_INT64,MPI_SUM,0,PetscObjectComm((PetscObject)pc)));
226fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = -1;
2279566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(loc,gmax,6,MPIU_INT64,MPI_MAX,0,PetscObjectComm((PetscObject)pc)));
228fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = PETSC_MAX_INT;
2299566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(loc,gmin,6,MPIU_INT64,MPI_MIN,0,PetscObjectComm((PetscObject)pc)));
2309566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&loc[6],&totbenign,1,MPIU_INT64,MPI_SUM,0,PetscObjectComm((PetscObject)pc)));
231e9627c49SStefano Zampini     if (pcbddc->coarse_size) {
232e9627c49SStefano Zampini       ratio1 = pc->pmat->rmap->N/(1.*pcbddc->coarse_size);
233e9627c49SStefano Zampini       ratio2 = PetscRealPart(interface_size)/pcbddc->coarse_size;
234e9627c49SStefano Zampini     }
23563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"********************************** STATISTICS AT LEVEL %" PetscInt_FMT " **********************************\n",pcbddc->current_level));
23663a3b9bcSJacob 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));
23763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Coarsening ratios: all/coarse %" PetscInt_FMT " interface/coarse %" PetscInt_FMT "\n",(PetscInt)ratio1,(PetscInt)ratio2));
23863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Active processes : %" PetscInt_FMT "\n",(PetscInt)gsum[0]));
23963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Total subdomains : %" PetscInt_FMT "\n",(PetscInt)gsum[5]));
240345ecf6cSStefano Zampini     if (pcbddc->benign_have_null) {
24163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer,"  Benign subs      : %" PetscInt_FMT "\n",(PetscInt)totbenign));
242345ecf6cSStefano Zampini     }
2439566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Dofs type        :\tMIN\tMAX\tMEAN\n"));
24463a3b9bcSJacob 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])));
24563a3b9bcSJacob 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])));
24663a3b9bcSJacob 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])));
24763a3b9bcSJacob 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])));
24863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Local     subs   :\t%" PetscInt_FMT "\t%" PetscInt_FMT "\n"    ,(PetscInt)gmin[5],(PetscInt)gmax[5]));
2499566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
25015579a77SStefano Zampini 
2519566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank));
25215579a77SStefano Zampini 
25315579a77SStefano Zampini     /* local solvers */
2549566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetSubViewer(viewer,PetscObjectComm((PetscObject)pcbddc->ksp_D),&subviewer));
255dd400576SPatrick Sanan     if (rank == 0) {
2569566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(subviewer,"--- Interior solver (rank 0)\n"));
2579566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(subviewer));
2589566063dSJacob Faibussowitsch       PetscCall(KSPView(pcbddc->ksp_D,subviewer));
2599566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(subviewer));
2609566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(subviewer,"--- Correction solver (rank 0)\n"));
2619566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(subviewer));
2629566063dSJacob Faibussowitsch       PetscCall(KSPView(pcbddc->ksp_R,subviewer));
2639566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(subviewer));
2649566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(subviewer));
26515579a77SStefano Zampini     }
2669566063dSJacob Faibussowitsch     PetscCall(PetscViewerRestoreSubViewer(viewer,PetscObjectComm((PetscObject)pcbddc->ksp_D),&subviewer));
2679566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
268e9627c49SStefano Zampini 
269fbad9177SStefano Zampini     /* the coarse problem can be handled by a different communicator */
270e9627c49SStefano Zampini     if (pcbddc->coarse_ksp) color = 1;
271e9627c49SStefano Zampini     else color = 0;
2729566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size));
2739566063dSJacob Faibussowitsch     PetscCall(PetscSubcommCreate(PetscObjectComm((PetscObject)pc),&subcomm));
2749566063dSJacob Faibussowitsch     PetscCall(PetscSubcommSetNumber(subcomm,PetscMin(size,2)));
2759566063dSJacob Faibussowitsch     PetscCall(PetscSubcommSetTypeGeneral(subcomm,color,rank));
2769566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer));
277e9627c49SStefano Zampini     if (color == 1) {
2789566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(subviewer,"--- Coarse solver\n"));
2799566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(subviewer));
2809566063dSJacob Faibussowitsch       PetscCall(KSPView(pcbddc->coarse_ksp,subviewer));
2819566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(subviewer));
2829566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(subviewer));
283e9627c49SStefano Zampini     }
2849566063dSJacob Faibussowitsch     PetscCall(PetscViewerRestoreSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer));
2859566063dSJacob Faibussowitsch     PetscCall(PetscSubcommDestroy(&subcomm));
2869566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
287e9627c49SStefano Zampini   }
2886b78500eSPatrick Sanan   PetscFunctionReturn(0);
2896b78500eSPatrick Sanan }
290a13144ffSStefano Zampini 
2911e0482f5SStefano Zampini static PetscErrorCode PCBDDCSetDiscreteGradient_BDDC(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
292a13144ffSStefano Zampini {
293a13144ffSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
294a13144ffSStefano Zampini 
295a13144ffSStefano Zampini   PetscFunctionBegin;
2969566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)G));
2979566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->discretegradient));
298a13144ffSStefano Zampini   pcbddc->discretegradient = G;
299a13144ffSStefano Zampini   pcbddc->nedorder         = order > 0 ? order : -order;
300495a2a07SStefano Zampini   pcbddc->nedfield         = field;
3011e0482f5SStefano Zampini   pcbddc->nedglobal        = global;
3021e0482f5SStefano Zampini   pcbddc->conforming       = conforming;
303a13144ffSStefano Zampini   PetscFunctionReturn(0);
304a13144ffSStefano Zampini }
305a13144ffSStefano Zampini 
306a13144ffSStefano Zampini /*@
307a13144ffSStefano Zampini  PCBDDCSetDiscreteGradient - Sets the discrete gradient
308a13144ffSStefano Zampini 
309a13144ffSStefano Zampini    Collective on PC
310a13144ffSStefano Zampini 
311a13144ffSStefano Zampini    Input Parameters:
312a13144ffSStefano Zampini +  pc         - the preconditioning context
313a13144ffSStefano Zampini .  G          - the discrete gradient matrix (should be in AIJ format)
314a13144ffSStefano Zampini .  order      - the order of the Nedelec space (1 for the lowest order)
315495a2a07SStefano Zampini .  field      - the field id of the Nedelec dofs (not used if the fields have not been specified)
3161e0482f5SStefano Zampini .  global     - the type of global ordering for the rows of G
317a13144ffSStefano Zampini -  conforming - whether the mesh is conforming or not
318a13144ffSStefano Zampini 
319a13144ffSStefano Zampini    Level: advanced
320a13144ffSStefano Zampini 
32195452b02SPatrick Sanan    Notes:
32295452b02SPatrick Sanan     The discrete gradient matrix G is used to analyze the subdomain edges, and it should not contain any zero entry.
323495a2a07SStefano Zampini           For variable order spaces, the order should be set to zero.
3241e0482f5SStefano Zampini           If global is true, the rows of G should be given in global ordering for the whole dofs;
3251e0482f5SStefano Zampini           if false, the ordering should be global for the Nedelec field.
3261e0482f5SStefano 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
3271e0482f5SStefano Zampini           and geid the one for the Nedelec field.
328a13144ffSStefano Zampini 
32916b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCSetDofsSplitting()`, `PCBDDCSetDofsSplittingLocal()`
330a13144ffSStefano Zampini @*/
3311e0482f5SStefano Zampini PetscErrorCode PCBDDCSetDiscreteGradient(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
332a13144ffSStefano Zampini {
333a13144ffSStefano Zampini   PetscFunctionBegin;
334a13144ffSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
335a13144ffSStefano Zampini   PetscValidHeaderSpecific(G,MAT_CLASSID,2);
336a13144ffSStefano Zampini   PetscValidLogicalCollectiveInt(pc,order,3);
3371e0482f5SStefano Zampini   PetscValidLogicalCollectiveInt(pc,field,4);
3381e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc,global,5);
3391e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc,conforming,6);
3401e0482f5SStefano Zampini   PetscCheckSameComm(pc,1,G,2);
341cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetDiscreteGradient_C",(PC,Mat,PetscInt,PetscInt,PetscBool,PetscBool),(pc,G,order,field,global,conforming));
342a13144ffSStefano Zampini   PetscFunctionReturn(0);
343a13144ffSStefano Zampini }
344a13144ffSStefano Zampini 
3458ae0ca82SStefano Zampini static PetscErrorCode PCBDDCSetDivergenceMat_BDDC(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
346a198735bSStefano Zampini {
347a198735bSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
3486b78500eSPatrick Sanan 
349a198735bSStefano Zampini   PetscFunctionBegin;
3509566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)divudotp));
3519566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->divudotp));
352a198735bSStefano Zampini   pcbddc->divudotp = divudotp;
3538ae0ca82SStefano Zampini   pcbddc->divudotp_trans = trans;
354a198735bSStefano Zampini   pcbddc->compute_nonetflux = PETSC_TRUE;
355a198735bSStefano Zampini   if (vl2l) {
3569566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)vl2l));
3579566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&pcbddc->divudotp_vl2l));
358a198735bSStefano Zampini     pcbddc->divudotp_vl2l = vl2l;
359a198735bSStefano Zampini   }
360a198735bSStefano Zampini   PetscFunctionReturn(0);
361a198735bSStefano Zampini }
3623d996552SStefano Zampini 
363a198735bSStefano Zampini /*@
364a198735bSStefano Zampini  PCBDDCSetDivergenceMat - Sets the linear operator representing \int_\Omega \div {\bf u} \cdot p dx
365a198735bSStefano Zampini 
366a198735bSStefano Zampini    Collective on PC
367a198735bSStefano Zampini 
368a198735bSStefano Zampini    Input Parameters:
369a198735bSStefano Zampini +  pc - the preconditioning context
370a198735bSStefano Zampini .  divudotp - the matrix (must be of type MATIS)
3718ae0ca82SStefano Zampini .  trans - if trans if false (resp. true), then pressures are in the test (trial) space and velocities are in the trial (test) space.
37205a3bf82SStefano Zampini -  vl2l - optional index set describing the local (wrt the local matrix in divudotp) to local (wrt the local matrix in the preconditioning matrix) map for the velocities
373a198735bSStefano Zampini 
374a198735bSStefano Zampini    Level: advanced
375a198735bSStefano Zampini 
37695452b02SPatrick Sanan    Notes:
37795452b02SPatrick Sanan     This auxiliary matrix is used to compute quadrature weights representing the net-flux across subdomain boundaries
37805a3bf82SStefano Zampini           If vl2l is NULL, the local ordering for velocities in divudotp should match that of the preconditioning matrix
379a198735bSStefano Zampini 
380db781477SPatrick Sanan .seealso: `PCBDDC`
381a198735bSStefano Zampini @*/
3828ae0ca82SStefano Zampini PetscErrorCode PCBDDCSetDivergenceMat(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
383a198735bSStefano Zampini {
384a198735bSStefano Zampini   PetscBool      ismatis;
385a198735bSStefano Zampini 
386a198735bSStefano Zampini   PetscFunctionBegin;
387a198735bSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
388a198735bSStefano Zampini   PetscValidHeaderSpecific(divudotp,MAT_CLASSID,2);
389a198735bSStefano Zampini   PetscCheckSameComm(pc,1,divudotp,2);
3908ae0ca82SStefano Zampini   PetscValidLogicalCollectiveBool(pc,trans,3);
3911b24a7afSStefano Zampini   if (vl2l) PetscValidHeaderSpecific(vl2l,IS_CLASSID,4);
3929566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)divudotp,MATIS,&ismatis));
39328b400f6SJacob Faibussowitsch   PetscCheck(ismatis,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Divergence matrix needs to be of type MATIS");
394cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetDivergenceMat_C",(PC,Mat,PetscBool,IS),(pc,divudotp,trans,vl2l));
395a198735bSStefano Zampini   PetscFunctionReturn(0);
396a198735bSStefano Zampini }
3972d505d7fSStefano Zampini 
3981dd7afcfSStefano Zampini static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change, PetscBool interior)
399b9b85e73SStefano Zampini {
400b9b85e73SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
401b9b85e73SStefano Zampini 
402b9b85e73SStefano Zampini   PetscFunctionBegin;
4039566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)change));
4049566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcbddc->user_ChangeOfBasisMatrix));
405b9b85e73SStefano Zampini   pcbddc->user_ChangeOfBasisMatrix = change;
4061dd7afcfSStefano Zampini   pcbddc->change_interior = interior;
407b9b85e73SStefano Zampini   PetscFunctionReturn(0);
408b9b85e73SStefano Zampini }
40932fe681dSStefano Zampini 
410b9b85e73SStefano Zampini /*@
411906d46d4SStefano Zampini  PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs
412b9b85e73SStefano Zampini 
413b9b85e73SStefano Zampini    Collective on PC
414b9b85e73SStefano Zampini 
415b9b85e73SStefano Zampini    Input Parameters:
416b9b85e73SStefano Zampini +  pc - the preconditioning context
4171dd7afcfSStefano Zampini .  change - the change of basis matrix
4181dd7afcfSStefano Zampini -  interior - whether or not the change of basis modifies interior dofs
419b9b85e73SStefano Zampini 
420b9b85e73SStefano Zampini    Level: intermediate
421b9b85e73SStefano Zampini 
422b9b85e73SStefano Zampini    Notes:
423b9b85e73SStefano Zampini 
424db781477SPatrick Sanan .seealso: `PCBDDC`
425b9b85e73SStefano Zampini @*/
4261dd7afcfSStefano Zampini PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change, PetscBool interior)
427b9b85e73SStefano Zampini {
428b9b85e73SStefano Zampini   PetscFunctionBegin;
429b9b85e73SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
430b9b85e73SStefano Zampini   PetscValidHeaderSpecific(change,MAT_CLASSID,2);
431906d46d4SStefano Zampini   PetscCheckSameComm(pc,1,change,2);
432906d46d4SStefano Zampini   if (pc->mat) {
433906d46d4SStefano Zampini     PetscInt rows_c,cols_c,rows,cols;
4349566063dSJacob Faibussowitsch     PetscCall(MatGetSize(pc->mat,&rows,&cols));
4359566063dSJacob Faibussowitsch     PetscCall(MatGetSize(change,&rows_c,&cols_c));
43663a3b9bcSJacob 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);
43763a3b9bcSJacob 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);
4389566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(pc->mat,&rows,&cols));
4399566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(change,&rows_c,&cols_c));
44063a3b9bcSJacob 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);
44163a3b9bcSJacob 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);
442906d46d4SStefano Zampini   }
443cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetChangeOfBasisMat_C",(PC,Mat,PetscBool),(pc,change,interior));
444b9b85e73SStefano Zampini   PetscFunctionReturn(0);
445b9b85e73SStefano Zampini }
4462d505d7fSStefano Zampini 
44730368db7SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesIS_BDDC(PC pc, IS PrimalVertices)
44830368db7SStefano Zampini {
44930368db7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
45056282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
45130368db7SStefano Zampini 
45230368db7SStefano Zampini   PetscFunctionBegin;
4539566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)PrimalVertices));
45456282151SStefano Zampini   if (pcbddc->user_primal_vertices) {
4559566063dSJacob Faibussowitsch     PetscCall(ISEqual(PrimalVertices,pcbddc->user_primal_vertices,&isequal));
45656282151SStefano Zampini   }
4579566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices));
4589566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local));
45930368db7SStefano Zampini   pcbddc->user_primal_vertices = PrimalVertices;
46056282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
46130368db7SStefano Zampini   PetscFunctionReturn(0);
46230368db7SStefano Zampini }
463ab8c8b98SStefano Zampini 
46430368db7SStefano Zampini /*@
46530368db7SStefano Zampini  PCBDDCSetPrimalVerticesIS - Set additional user defined primal vertices in PCBDDC
46630368db7SStefano Zampini 
46730368db7SStefano Zampini    Collective
46830368db7SStefano Zampini 
46930368db7SStefano Zampini    Input Parameters:
47030368db7SStefano Zampini +  pc - the preconditioning context
47130368db7SStefano Zampini -  PrimalVertices - index set of primal vertices in global numbering (can be empty)
47230368db7SStefano Zampini 
47330368db7SStefano Zampini    Level: intermediate
47430368db7SStefano Zampini 
47530368db7SStefano Zampini    Notes:
47630368db7SStefano Zampini      Any process can list any global node
47730368db7SStefano Zampini 
478db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`, `PCBDDCGetPrimalVerticesLocalIS()`
47930368db7SStefano Zampini @*/
48030368db7SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesIS(PC pc, IS PrimalVertices)
48130368db7SStefano Zampini {
48230368db7SStefano Zampini   PetscFunctionBegin;
48330368db7SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
48430368db7SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
48530368db7SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
486cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetPrimalVerticesIS_C",(PC,IS),(pc,PrimalVertices));
48730368db7SStefano Zampini   PetscFunctionReturn(0);
48830368db7SStefano Zampini }
4892d505d7fSStefano Zampini 
4903100ebe3SStefano Zampini static PetscErrorCode PCBDDCGetPrimalVerticesIS_BDDC(PC pc, IS *is)
4913100ebe3SStefano Zampini {
4923100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC*)pc->data;
4933100ebe3SStefano Zampini 
4943100ebe3SStefano Zampini   PetscFunctionBegin;
4953100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices;
4963100ebe3SStefano Zampini   PetscFunctionReturn(0);
4973100ebe3SStefano Zampini }
4983100ebe3SStefano Zampini 
4993100ebe3SStefano Zampini /*@
5003100ebe3SStefano Zampini  PCBDDCGetPrimalVerticesIS - Get user defined primal vertices set with PCBDDCSetPrimalVerticesIS()
5013100ebe3SStefano Zampini 
5023100ebe3SStefano Zampini    Collective
5033100ebe3SStefano Zampini 
5043100ebe3SStefano Zampini    Input Parameters:
5053100ebe3SStefano Zampini .  pc - the preconditioning context
5063100ebe3SStefano Zampini 
5073100ebe3SStefano Zampini    Output Parameters:
5083100ebe3SStefano Zampini .  is - index set of primal vertices in global numbering (NULL if not set)
5093100ebe3SStefano Zampini 
5103100ebe3SStefano Zampini    Level: intermediate
5113100ebe3SStefano Zampini 
5123100ebe3SStefano Zampini    Notes:
5133100ebe3SStefano Zampini 
514db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`, `PCBDDCGetPrimalVerticesLocalIS()`
5153100ebe3SStefano Zampini @*/
5163100ebe3SStefano Zampini PetscErrorCode PCBDDCGetPrimalVerticesIS(PC pc, IS *is)
5173100ebe3SStefano Zampini {
5183100ebe3SStefano Zampini   PetscFunctionBegin;
5193100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5203100ebe3SStefano Zampini   PetscValidPointer(is,2);
521cac4c232SBarry Smith   PetscUseMethod(pc,"PCBDDCGetPrimalVerticesIS_C",(PC,IS*),(pc,is));
5223100ebe3SStefano Zampini   PetscFunctionReturn(0);
5233100ebe3SStefano Zampini }
5243100ebe3SStefano Zampini 
525674ae819SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
526674ae819SStefano Zampini {
527674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
52856282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
5291e6b0712SBarry Smith 
530674ae819SStefano Zampini   PetscFunctionBegin;
5319566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)PrimalVertices));
53256282151SStefano Zampini   if (pcbddc->user_primal_vertices_local) {
5339566063dSJacob Faibussowitsch     PetscCall(ISEqual(PrimalVertices,pcbddc->user_primal_vertices_local,&isequal));
53456282151SStefano Zampini   }
5359566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices));
5369566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local));
53730368db7SStefano Zampini   pcbddc->user_primal_vertices_local = PrimalVertices;
53856282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
539674ae819SStefano Zampini   PetscFunctionReturn(0);
540674ae819SStefano Zampini }
5413100ebe3SStefano Zampini 
542674ae819SStefano Zampini /*@
54328509bceSStefano Zampini  PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in PCBDDC
544674ae819SStefano Zampini 
54517eb1463SStefano Zampini    Collective
546674ae819SStefano Zampini 
547674ae819SStefano Zampini    Input Parameters:
548674ae819SStefano Zampini +  pc - the preconditioning context
54917eb1463SStefano Zampini -  PrimalVertices - index set of primal vertices in local numbering (can be empty)
550674ae819SStefano Zampini 
551674ae819SStefano Zampini    Level: intermediate
552674ae819SStefano Zampini 
553674ae819SStefano Zampini    Notes:
554674ae819SStefano Zampini 
555db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesLocalIS()`
556674ae819SStefano Zampini @*/
557674ae819SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
558674ae819SStefano Zampini {
559674ae819SStefano Zampini   PetscFunctionBegin;
560674ae819SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
561674ae819SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
56217eb1463SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
563cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));
564674ae819SStefano Zampini   PetscFunctionReturn(0);
565674ae819SStefano Zampini }
5662d505d7fSStefano Zampini 
5673100ebe3SStefano Zampini static PetscErrorCode PCBDDCGetPrimalVerticesLocalIS_BDDC(PC pc, IS *is)
5683100ebe3SStefano Zampini {
5693100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC*)pc->data;
5703100ebe3SStefano Zampini 
5713100ebe3SStefano Zampini   PetscFunctionBegin;
5723100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices_local;
5733100ebe3SStefano Zampini   PetscFunctionReturn(0);
5743100ebe3SStefano Zampini }
5753100ebe3SStefano Zampini 
5763100ebe3SStefano Zampini /*@
5773100ebe3SStefano Zampini  PCBDDCGetPrimalVerticesLocalIS - Get user defined primal vertices set with PCBDDCSetPrimalVerticesLocalIS()
5783100ebe3SStefano Zampini 
5793100ebe3SStefano Zampini    Collective
5803100ebe3SStefano Zampini 
5813100ebe3SStefano Zampini    Input Parameters:
5823100ebe3SStefano Zampini .  pc - the preconditioning context
5833100ebe3SStefano Zampini 
5843100ebe3SStefano Zampini    Output Parameters:
5853100ebe3SStefano Zampini .  is - index set of primal vertices in local numbering (NULL if not set)
5863100ebe3SStefano Zampini 
5873100ebe3SStefano Zampini    Level: intermediate
5883100ebe3SStefano Zampini 
5893100ebe3SStefano Zampini    Notes:
5903100ebe3SStefano Zampini 
591db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`
5923100ebe3SStefano Zampini @*/
5933100ebe3SStefano Zampini PetscErrorCode PCBDDCGetPrimalVerticesLocalIS(PC pc, IS *is)
5943100ebe3SStefano Zampini {
5953100ebe3SStefano Zampini   PetscFunctionBegin;
5963100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5973100ebe3SStefano Zampini   PetscValidPointer(is,2);
598cac4c232SBarry Smith   PetscUseMethod(pc,"PCBDDCGetPrimalVerticesLocalIS_C",(PC,IS*),(pc,is));
5993100ebe3SStefano Zampini   PetscFunctionReturn(0);
6003100ebe3SStefano Zampini }
6013100ebe3SStefano Zampini 
6024fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k)
6034fad6a16SStefano Zampini {
6044fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
6054fad6a16SStefano Zampini 
6064fad6a16SStefano Zampini   PetscFunctionBegin;
6074fad6a16SStefano Zampini   pcbddc->coarsening_ratio = k;
6084fad6a16SStefano Zampini   PetscFunctionReturn(0);
6094fad6a16SStefano Zampini }
6101e6b0712SBarry Smith 
6114fad6a16SStefano Zampini /*@
61228509bceSStefano Zampini  PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel
6134fad6a16SStefano Zampini 
6144fad6a16SStefano Zampini    Logically collective on PC
6154fad6a16SStefano Zampini 
6164fad6a16SStefano Zampini    Input Parameters:
6174fad6a16SStefano Zampini +  pc - the preconditioning context
61828509bceSStefano Zampini -  k - coarsening ratio (H/h at the coarser level)
6194fad6a16SStefano Zampini 
6200f202f7eSStefano Zampini    Options Database Keys:
62167b8a455SSatish Balay .    -pc_bddc_coarsening_ratio <int> - Set coarsening ratio used in multilevel coarsening
6224fad6a16SStefano Zampini 
6234fad6a16SStefano Zampini    Level: intermediate
6244fad6a16SStefano Zampini 
6254fad6a16SStefano Zampini    Notes:
6260f202f7eSStefano Zampini      Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level
6274fad6a16SStefano Zampini 
628db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetLevels()`
6294fad6a16SStefano Zampini @*/
6304fad6a16SStefano Zampini PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k)
6314fad6a16SStefano Zampini {
6324fad6a16SStefano Zampini   PetscFunctionBegin;
6334fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
6342b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,k,2);
635cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));
6364fad6a16SStefano Zampini   PetscFunctionReturn(0);
6374fad6a16SStefano Zampini }
6382b510759SStefano Zampini 
639b8ffe317SStefano Zampini /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */
640b8ffe317SStefano Zampini static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc,PetscBool flg)
641b8ffe317SStefano Zampini {
642b8ffe317SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
643b8ffe317SStefano Zampini 
644b8ffe317SStefano Zampini   PetscFunctionBegin;
64585c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = flg;
646b8ffe317SStefano Zampini   PetscFunctionReturn(0);
647b8ffe317SStefano Zampini }
648b8ffe317SStefano Zampini 
649b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool flg)
6502b510759SStefano Zampini {
6512b510759SStefano Zampini   PetscFunctionBegin;
6522b510759SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
653b8ffe317SStefano Zampini   PetscValidLogicalCollectiveBool(pc,flg,2);
654cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetUseExactDirichlet_C",(PC,PetscBool),(pc,flg));
6552b510759SStefano Zampini   PetscFunctionReturn(0);
6562b510759SStefano Zampini }
6571e6b0712SBarry Smith 
6582b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc,PetscInt level)
6594fad6a16SStefano Zampini {
6604fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
6614fad6a16SStefano Zampini 
6624fad6a16SStefano Zampini   PetscFunctionBegin;
6632b510759SStefano Zampini   pcbddc->current_level = level;
6644fad6a16SStefano Zampini   PetscFunctionReturn(0);
6654fad6a16SStefano Zampini }
6661e6b0712SBarry Smith 
667b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level)
668b8ffe317SStefano Zampini {
669b8ffe317SStefano Zampini   PetscFunctionBegin;
670b8ffe317SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
671b8ffe317SStefano Zampini   PetscValidLogicalCollectiveInt(pc,level,2);
672cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetLevel_C",(PC,PetscInt),(pc,level));
673b8ffe317SStefano Zampini   PetscFunctionReturn(0);
674b8ffe317SStefano Zampini }
675b8ffe317SStefano Zampini 
6762b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc,PetscInt levels)
6772b510759SStefano Zampini {
6782b510759SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
6792b510759SStefano Zampini 
6802b510759SStefano Zampini   PetscFunctionBegin;
6817827d75bSBarry 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);
6822b510759SStefano Zampini   pcbddc->max_levels = levels;
6832b510759SStefano Zampini   PetscFunctionReturn(0);
6842b510759SStefano Zampini }
6852b510759SStefano Zampini 
6864fad6a16SStefano Zampini /*@
68737ebbdf7SStefano Zampini  PCBDDCSetLevels - Sets the maximum number of additional levels allowed for multilevel BDDC
6884fad6a16SStefano Zampini 
6894fad6a16SStefano Zampini    Logically collective on PC
6904fad6a16SStefano Zampini 
6914fad6a16SStefano Zampini    Input Parameters:
6924fad6a16SStefano Zampini +  pc - the preconditioning context
69337ebbdf7SStefano Zampini -  levels - the maximum number of levels
6944fad6a16SStefano Zampini 
6950f202f7eSStefano Zampini    Options Database Keys:
69667b8a455SSatish Balay .    -pc_bddc_levels <int> - Set maximum number of levels for multilevel
6974fad6a16SStefano Zampini 
6984fad6a16SStefano Zampini    Level: intermediate
6994fad6a16SStefano Zampini 
7004fad6a16SStefano Zampini    Notes:
70137ebbdf7SStefano Zampini      The default value is 0, that gives the classical two-levels BDDC
7024fad6a16SStefano Zampini 
703db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetCoarseningRatio()`
7044fad6a16SStefano Zampini @*/
7052b510759SStefano Zampini PetscErrorCode PCBDDCSetLevels(PC pc,PetscInt levels)
7064fad6a16SStefano Zampini {
7074fad6a16SStefano Zampini   PetscFunctionBegin;
7084fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
7092b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,levels,2);
710cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetLevels_C",(PC,PetscInt),(pc,levels));
7114fad6a16SStefano Zampini   PetscFunctionReturn(0);
7124fad6a16SStefano Zampini }
7131e6b0712SBarry Smith 
7143b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
7153b03a366Sstefano_zampini {
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));
72156282151SStefano Zampini   if (pcbddc->DirichletBoundaries) {
7229566063dSJacob Faibussowitsch     PetscCall(ISEqual(DirichletBoundaries,pcbddc->DirichletBoundaries,&isequal));
72356282151SStefano Zampini   }
724a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
7259566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal));
7269566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundaries));
72736e030ebSStefano Zampini   pcbddc->DirichletBoundaries = DirichletBoundaries;
72856282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7293b03a366Sstefano_zampini   PetscFunctionReturn(0);
7303b03a366Sstefano_zampini }
7311e6b0712SBarry Smith 
7323b03a366Sstefano_zampini /*@
73328509bceSStefano Zampini  PCBDDCSetDirichletBoundaries - Set IS defining Dirichlet boundaries for the global problem.
7343b03a366Sstefano_zampini 
735785d1243SStefano Zampini    Collective
7363b03a366Sstefano_zampini 
7373b03a366Sstefano_zampini    Input Parameters:
7383b03a366Sstefano_zampini +  pc - the preconditioning context
739785d1243SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries
7403b03a366Sstefano_zampini 
7413b03a366Sstefano_zampini    Level: intermediate
7423b03a366Sstefano_zampini 
7430f202f7eSStefano Zampini    Notes:
7440f202f7eSStefano Zampini      Provide the information if you used MatZeroRows/Columns routines. Any process can list any global node
7453b03a366Sstefano_zampini 
746db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetDirichletBoundariesLocal()`, `MatZeroRows()`, `MatZeroRowsColumns()`
7473b03a366Sstefano_zampini @*/
7483b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
7493b03a366Sstefano_zampini {
7503b03a366Sstefano_zampini   PetscFunctionBegin;
7513b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
752674ae819SStefano Zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
753785d1243SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
754cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));
7553b03a366Sstefano_zampini   PetscFunctionReturn(0);
7563b03a366Sstefano_zampini }
7571e6b0712SBarry Smith 
75882ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc,IS DirichletBoundaries)
7593b03a366Sstefano_zampini {
7603b03a366Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
76156282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
7623b03a366Sstefano_zampini 
7633b03a366Sstefano_zampini   PetscFunctionBegin;
7649566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)DirichletBoundaries));
76556282151SStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
7669566063dSJacob Faibussowitsch     PetscCall(ISEqual(DirichletBoundaries,pcbddc->DirichletBoundariesLocal,&isequal));
76756282151SStefano Zampini   }
768a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
7699566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal));
7709566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundaries));
771785d1243SStefano Zampini   pcbddc->DirichletBoundariesLocal = DirichletBoundaries;
77256282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7733b03a366Sstefano_zampini   PetscFunctionReturn(0);
7743b03a366Sstefano_zampini }
7753b03a366Sstefano_zampini 
7763b03a366Sstefano_zampini /*@
77782ba6b80SStefano Zampini  PCBDDCSetDirichletBoundariesLocal - Set IS defining Dirichlet boundaries for the global problem in local ordering.
7783b03a366Sstefano_zampini 
779785d1243SStefano Zampini    Collective
7803b03a366Sstefano_zampini 
7813b03a366Sstefano_zampini    Input Parameters:
7823b03a366Sstefano_zampini +  pc - the preconditioning context
78382ba6b80SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries (in local ordering)
7843b03a366Sstefano_zampini 
7853b03a366Sstefano_zampini    Level: intermediate
7863b03a366Sstefano_zampini 
7873b03a366Sstefano_zampini    Notes:
7883b03a366Sstefano_zampini 
789db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetDirichletBoundaries()`, `MatZeroRows()`, `MatZeroRowsColumns()`
7903b03a366Sstefano_zampini @*/
79182ba6b80SStefano Zampini PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc,IS DirichletBoundaries)
7923b03a366Sstefano_zampini {
7933b03a366Sstefano_zampini   PetscFunctionBegin;
7943b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
7953b03a366Sstefano_zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
79682ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
797cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetDirichletBoundariesLocal_C",(PC,IS),(pc,DirichletBoundaries));
7983b03a366Sstefano_zampini   PetscFunctionReturn(0);
7993b03a366Sstefano_zampini }
8003b03a366Sstefano_zampini 
80153cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
8020c7d97c5SJed Brown {
8030c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
80456282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
8050c7d97c5SJed Brown 
8060c7d97c5SJed Brown   PetscFunctionBegin;
8079566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries));
80856282151SStefano Zampini   if (pcbddc->NeumannBoundaries) {
8099566063dSJacob Faibussowitsch     PetscCall(ISEqual(NeumannBoundaries,pcbddc->NeumannBoundaries,&isequal));
81056282151SStefano Zampini   }
811a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
8129566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal));
8139566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundaries));
81436e030ebSStefano Zampini   pcbddc->NeumannBoundaries = NeumannBoundaries;
81556282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
8160c7d97c5SJed Brown   PetscFunctionReturn(0);
8170c7d97c5SJed Brown }
8181e6b0712SBarry Smith 
81957527edcSJed Brown /*@
82028509bceSStefano Zampini  PCBDDCSetNeumannBoundaries - Set IS defining Neumann boundaries for the global problem.
82157527edcSJed Brown 
822785d1243SStefano Zampini    Collective
82357527edcSJed Brown 
82457527edcSJed Brown    Input Parameters:
82557527edcSJed Brown +  pc - the preconditioning context
826785d1243SStefano Zampini -  NeumannBoundaries - parallel IS defining the Neumann boundaries
82757527edcSJed Brown 
82857527edcSJed Brown    Level: intermediate
82957527edcSJed Brown 
8300f202f7eSStefano Zampini    Notes:
8310f202f7eSStefano Zampini      Any process can list any global node
83257527edcSJed Brown 
833db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetNeumannBoundariesLocal()`
83457527edcSJed Brown @*/
83553cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
8360c7d97c5SJed Brown {
8370c7d97c5SJed Brown   PetscFunctionBegin;
8380c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
839674ae819SStefano Zampini   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
840785d1243SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
841cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));
84253cdbc3dSStefano Zampini   PetscFunctionReturn(0);
84353cdbc3dSStefano Zampini }
8441e6b0712SBarry Smith 
84582ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc,IS NeumannBoundaries)
8460c7d97c5SJed Brown {
8470c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
84856282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
8490c7d97c5SJed Brown 
8500c7d97c5SJed Brown   PetscFunctionBegin;
8519566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries));
85256282151SStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
8539566063dSJacob Faibussowitsch     PetscCall(ISEqual(NeumannBoundaries,pcbddc->NeumannBoundariesLocal,&isequal));
85456282151SStefano Zampini   }
855a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
8569566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal));
8579566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundaries));
858785d1243SStefano Zampini   pcbddc->NeumannBoundariesLocal = NeumannBoundaries;
85956282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
8600c7d97c5SJed Brown   PetscFunctionReturn(0);
8610c7d97c5SJed Brown }
8620c7d97c5SJed Brown 
8630c7d97c5SJed Brown /*@
86482ba6b80SStefano Zampini  PCBDDCSetNeumannBoundariesLocal - Set IS defining Neumann boundaries for the global problem in local ordering.
8650c7d97c5SJed Brown 
866785d1243SStefano Zampini    Collective
8670c7d97c5SJed Brown 
8680c7d97c5SJed Brown    Input Parameters:
8690c7d97c5SJed Brown +  pc - the preconditioning context
87082ba6b80SStefano Zampini -  NeumannBoundaries - parallel IS defining the subdomain part of Neumann boundaries (in local ordering)
8710c7d97c5SJed Brown 
8720c7d97c5SJed Brown    Level: intermediate
8730c7d97c5SJed Brown 
8740c7d97c5SJed Brown    Notes:
8750c7d97c5SJed Brown 
876db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetNeumannBoundaries()`
8770c7d97c5SJed Brown @*/
87882ba6b80SStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc,IS NeumannBoundaries)
8790c7d97c5SJed Brown {
8800c7d97c5SJed Brown   PetscFunctionBegin;
8810c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
8820c7d97c5SJed Brown   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
88382ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
884cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetNeumannBoundariesLocal_C",(PC,IS),(pc,NeumannBoundaries));
88553cdbc3dSStefano Zampini   PetscFunctionReturn(0);
88653cdbc3dSStefano Zampini }
88753cdbc3dSStefano Zampini 
888da1bb401SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
889da1bb401SStefano Zampini {
890da1bb401SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
891da1bb401SStefano Zampini 
892da1bb401SStefano Zampini   PetscFunctionBegin;
893da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
894da1bb401SStefano Zampini   PetscFunctionReturn(0);
895da1bb401SStefano Zampini }
8961e6b0712SBarry Smith 
897da1bb401SStefano Zampini /*@
898785d1243SStefano Zampini  PCBDDCGetDirichletBoundaries - Get parallel IS for Dirichlet boundaries
899da1bb401SStefano Zampini 
900785d1243SStefano Zampini    Collective
901785d1243SStefano Zampini 
902785d1243SStefano Zampini    Input Parameters:
903785d1243SStefano Zampini .  pc - the preconditioning context
904785d1243SStefano Zampini 
905785d1243SStefano Zampini    Output Parameters:
906785d1243SStefano Zampini .  DirichletBoundaries - index set defining the Dirichlet boundaries
907785d1243SStefano Zampini 
908785d1243SStefano Zampini    Level: intermediate
909785d1243SStefano Zampini 
9100f202f7eSStefano Zampini    Notes:
9110f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetDirichletBoundaries
912785d1243SStefano Zampini 
913db781477SPatrick Sanan .seealso: `PCBDDC`
914785d1243SStefano Zampini @*/
915785d1243SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
916785d1243SStefano Zampini {
917785d1243SStefano Zampini   PetscFunctionBegin;
918785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
919cac4c232SBarry Smith   PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));
920785d1243SStefano Zampini   PetscFunctionReturn(0);
921785d1243SStefano Zampini }
922785d1243SStefano Zampini 
923785d1243SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc,IS *DirichletBoundaries)
924785d1243SStefano Zampini {
925785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
926785d1243SStefano Zampini 
927785d1243SStefano Zampini   PetscFunctionBegin;
928785d1243SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundariesLocal;
929785d1243SStefano Zampini   PetscFunctionReturn(0);
930785d1243SStefano Zampini }
931785d1243SStefano Zampini 
932da1bb401SStefano Zampini /*@
93382ba6b80SStefano Zampini  PCBDDCGetDirichletBoundariesLocal - Get parallel IS for Dirichlet boundaries (in local ordering)
934da1bb401SStefano Zampini 
935785d1243SStefano Zampini    Collective
936da1bb401SStefano Zampini 
937da1bb401SStefano Zampini    Input Parameters:
93828509bceSStefano Zampini .  pc - the preconditioning context
939da1bb401SStefano Zampini 
940da1bb401SStefano Zampini    Output Parameters:
94128509bceSStefano Zampini .  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
942da1bb401SStefano Zampini 
943da1bb401SStefano Zampini    Level: intermediate
944da1bb401SStefano Zampini 
945da1bb401SStefano Zampini    Notes:
9460f202f7eSStefano Zampini      The IS returned could be the same passed in earlier by the user (if provided with PCBDDCSetDirichletBoundariesLocal) or a global-to-local map of the global IS (if provided with PCBDDCSetDirichletBoundaries).
9470f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
948da1bb401SStefano Zampini 
949db781477SPatrick Sanan .seealso: `PCBDDC`
950da1bb401SStefano Zampini @*/
95182ba6b80SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc,IS *DirichletBoundaries)
952da1bb401SStefano Zampini {
953da1bb401SStefano Zampini   PetscFunctionBegin;
954da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
955cac4c232SBarry Smith   PetscUseMethod(pc,"PCBDDCGetDirichletBoundariesLocal_C",(PC,IS*),(pc,DirichletBoundaries));
956da1bb401SStefano Zampini   PetscFunctionReturn(0);
957da1bb401SStefano Zampini }
9581e6b0712SBarry Smith 
95953cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
96053cdbc3dSStefano Zampini {
96153cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
96253cdbc3dSStefano Zampini 
96353cdbc3dSStefano Zampini   PetscFunctionBegin;
96453cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
96553cdbc3dSStefano Zampini   PetscFunctionReturn(0);
96653cdbc3dSStefano Zampini }
9671e6b0712SBarry Smith 
96853cdbc3dSStefano Zampini /*@
969785d1243SStefano Zampini  PCBDDCGetNeumannBoundaries - Get parallel IS for Neumann boundaries
97053cdbc3dSStefano Zampini 
971785d1243SStefano Zampini    Collective
972785d1243SStefano Zampini 
973785d1243SStefano Zampini    Input Parameters:
974785d1243SStefano Zampini .  pc - the preconditioning context
975785d1243SStefano Zampini 
976785d1243SStefano Zampini    Output Parameters:
977785d1243SStefano Zampini .  NeumannBoundaries - index set defining the Neumann boundaries
978785d1243SStefano Zampini 
979785d1243SStefano Zampini    Level: intermediate
980785d1243SStefano Zampini 
9810f202f7eSStefano Zampini    Notes:
9820f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetNeumannBoundaries
983785d1243SStefano Zampini 
984db781477SPatrick Sanan .seealso: `PCBDDC`
985785d1243SStefano Zampini @*/
986785d1243SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
987785d1243SStefano Zampini {
988785d1243SStefano Zampini   PetscFunctionBegin;
989785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
990cac4c232SBarry Smith   PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));
991785d1243SStefano Zampini   PetscFunctionReturn(0);
992785d1243SStefano Zampini }
993785d1243SStefano Zampini 
994785d1243SStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc,IS *NeumannBoundaries)
995785d1243SStefano Zampini {
996785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
997785d1243SStefano Zampini 
998785d1243SStefano Zampini   PetscFunctionBegin;
999785d1243SStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundariesLocal;
1000785d1243SStefano Zampini   PetscFunctionReturn(0);
1001785d1243SStefano Zampini }
1002785d1243SStefano Zampini 
100353cdbc3dSStefano Zampini /*@
100482ba6b80SStefano Zampini  PCBDDCGetNeumannBoundariesLocal - Get parallel IS for Neumann boundaries (in local ordering)
100553cdbc3dSStefano Zampini 
1006785d1243SStefano Zampini    Collective
100753cdbc3dSStefano Zampini 
100853cdbc3dSStefano Zampini    Input Parameters:
100928509bceSStefano Zampini .  pc - the preconditioning context
101053cdbc3dSStefano Zampini 
101153cdbc3dSStefano Zampini    Output Parameters:
101228509bceSStefano Zampini .  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
101353cdbc3dSStefano Zampini 
101453cdbc3dSStefano Zampini    Level: intermediate
101553cdbc3dSStefano Zampini 
101653cdbc3dSStefano Zampini    Notes:
10170f202f7eSStefano Zampini      The IS returned could be the same passed in earlier by the user (if provided with PCBDDCSetNeumannBoundariesLocal) or a global-to-local map of the global IS (if provided with PCBDDCSetNeumannBoundaries).
10180f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
101953cdbc3dSStefano Zampini 
1020db781477SPatrick Sanan .seealso: `PCBDDC`
102153cdbc3dSStefano Zampini @*/
102282ba6b80SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc,IS *NeumannBoundaries)
102353cdbc3dSStefano Zampini {
102453cdbc3dSStefano Zampini   PetscFunctionBegin;
102553cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1026cac4c232SBarry Smith   PetscUseMethod(pc,"PCBDDCGetNeumannBoundariesLocal_C",(PC,IS*),(pc,NeumannBoundaries));
10270c7d97c5SJed Brown   PetscFunctionReturn(0);
10280c7d97c5SJed Brown }
10291e6b0712SBarry Smith 
10301a83f524SJed Brown static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
103136e030ebSStefano Zampini {
103236e030ebSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1033da1bb401SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
103456282151SStefano Zampini   PetscBool      same_data = PETSC_FALSE;
103536e030ebSStefano Zampini 
103636e030ebSStefano Zampini   PetscFunctionBegin;
10378687889aSStefano Zampini   if (!nvtxs) {
103804194a47SStefano Zampini     if (copymode == PETSC_OWN_POINTER) {
10399566063dSJacob Faibussowitsch       PetscCall(PetscFree(xadj));
10409566063dSJacob Faibussowitsch       PetscCall(PetscFree(adjncy));
104104194a47SStefano Zampini     }
10429566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphResetCSR(mat_graph));
10438687889aSStefano Zampini     PetscFunctionReturn(0);
10448687889aSStefano Zampini   }
104566da6bd7Sstefano_zampini   if (mat_graph->nvtxs == nvtxs && mat_graph->freecsr) { /* we own the data */
104656282151SStefano Zampini     if (mat_graph->xadj == xadj && mat_graph->adjncy == adjncy) same_data = PETSC_TRUE;
104756282151SStefano Zampini     if (!same_data && mat_graph->xadj[nvtxs] == xadj[nvtxs]) {
10489566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(xadj,mat_graph->xadj,nvtxs+1,&same_data));
10492d505d7fSStefano Zampini       if (same_data) {
10509566063dSJacob Faibussowitsch         PetscCall(PetscArraycmp(adjncy,mat_graph->adjncy,xadj[nvtxs],&same_data));
10512d505d7fSStefano Zampini       }
105256282151SStefano Zampini     }
105356282151SStefano Zampini   }
105456282151SStefano Zampini   if (!same_data) {
1055674ae819SStefano Zampini     /* free old CSR */
10569566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphResetCSR(mat_graph));
1057674ae819SStefano Zampini     /* get CSR into graph structure */
1058da1bb401SStefano Zampini     if (copymode == PETSC_COPY_VALUES) {
10599566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvtxs+1,&mat_graph->xadj));
10609566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(xadj[nvtxs],&mat_graph->adjncy));
10619566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(mat_graph->xadj,xadj,nvtxs+1));
10629566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(mat_graph->adjncy,adjncy,xadj[nvtxs]));
1063a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1064da1bb401SStefano Zampini     } else if (copymode == PETSC_OWN_POINTER) {
10651a83f524SJed Brown       mat_graph->xadj    = (PetscInt*)xadj;
10661a83f524SJed Brown       mat_graph->adjncy  = (PetscInt*)adjncy;
1067a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1068a1dbd327SStefano Zampini     } else if (copymode == PETSC_USE_POINTER) {
1069a1dbd327SStefano Zampini       mat_graph->xadj    = (PetscInt*)xadj;
1070a1dbd327SStefano Zampini       mat_graph->adjncy  = (PetscInt*)adjncy;
1071a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_FALSE;
107263a3b9bcSJacob Faibussowitsch     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %d",copymode);
1073575ad6abSStefano Zampini     mat_graph->nvtxs_csr = nvtxs;
107456282151SStefano Zampini     pcbddc->recompute_topography = PETSC_TRUE;
107556282151SStefano Zampini   }
107636e030ebSStefano Zampini   PetscFunctionReturn(0);
107736e030ebSStefano Zampini }
10781e6b0712SBarry Smith 
107936e030ebSStefano Zampini /*@
108054fffbccSStefano Zampini  PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local degrees of freedom.
108136e030ebSStefano Zampini 
108236e030ebSStefano Zampini    Not collective
108336e030ebSStefano Zampini 
108436e030ebSStefano Zampini    Input Parameters:
108554fffbccSStefano Zampini +  pc - the preconditioning context.
108654fffbccSStefano Zampini .  nvtxs - number of local vertices of the graph (i.e., the number of local dofs).
108754fffbccSStefano Zampini .  xadj, adjncy - the connectivity of the dofs in CSR format.
108854fffbccSStefano Zampini -  copymode - supported modes are PETSC_COPY_VALUES, PETSC_USE_POINTER or PETSC_OWN_POINTER.
108936e030ebSStefano Zampini 
109036e030ebSStefano Zampini    Level: intermediate
109136e030ebSStefano Zampini 
109295452b02SPatrick Sanan    Notes:
109395452b02SPatrick Sanan     A dof is considered connected with all local dofs if xadj[dof+1]-xadj[dof] == 1 and adjncy[xadj[dof]] is negative.
109436e030ebSStefano Zampini 
109516b07851SJed Brown .seealso: `PCBDDC`, `PetscCopyMode`
109636e030ebSStefano Zampini @*/
10971a83f524SJed Brown PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
109836e030ebSStefano Zampini {
10990a545947SLisandro Dalcin   void (*f)(void) = NULL;
110036e030ebSStefano Zampini 
110136e030ebSStefano Zampini   PetscFunctionBegin;
110236e030ebSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
11038687889aSStefano Zampini   if (nvtxs) {
1104674ae819SStefano Zampini     PetscValidIntPointer(xadj,3);
11051633d1f0SStefano Zampini     if (xadj[nvtxs]) PetscValidIntPointer(adjncy,4);
11068687889aSStefano Zampini   }
1107cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));
1108575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
11099566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f));
1110575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
11119566063dSJacob Faibussowitsch     PetscCall(PetscFree(xadj));
11129566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjncy));
1113da1bb401SStefano Zampini   }
111436e030ebSStefano Zampini   PetscFunctionReturn(0);
111536e030ebSStefano Zampini }
11161e6b0712SBarry Smith 
111763602bcaSStefano Zampini static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
111863602bcaSStefano Zampini {
111963602bcaSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
112063602bcaSStefano Zampini   PetscInt       i;
112156282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
112263602bcaSStefano Zampini 
112363602bcaSStefano Zampini   PetscFunctionBegin;
112456282151SStefano Zampini   if (pcbddc->n_ISForDofsLocal == n_is) {
112556282151SStefano Zampini     for (i=0;i<n_is;i++) {
112656282151SStefano Zampini       PetscBool isequalt;
11279566063dSJacob Faibussowitsch       PetscCall(ISEqual(ISForDofs[i],pcbddc->ISForDofsLocal[i],&isequalt));
112856282151SStefano Zampini       if (!isequalt) break;
112956282151SStefano Zampini     }
113056282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
113156282151SStefano Zampini   }
113256282151SStefano Zampini   for (i=0;i<n_is;i++) {
11339566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)ISForDofs[i]));
113456282151SStefano Zampini   }
113563602bcaSStefano Zampini   /* Destroy ISes if they were already set */
113663602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
11379566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i]));
113863602bcaSStefano Zampini   }
11399566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofsLocal));
1140a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
114163602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
11429566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&pcbddc->ISForDofs[i]));
114363602bcaSStefano Zampini   }
11449566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofs));
114563602bcaSStefano Zampini   pcbddc->n_ISForDofs = 0;
114663602bcaSStefano Zampini   /* allocate space then set */
1147d02579f5SStefano Zampini   if (n_is) {
11489566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n_is,&pcbddc->ISForDofsLocal));
1149d02579f5SStefano Zampini   }
115063602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
115163602bcaSStefano Zampini     pcbddc->ISForDofsLocal[i] = ISForDofs[i];
115263602bcaSStefano Zampini   }
115363602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = n_is;
115463602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
115556282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
115663602bcaSStefano Zampini   PetscFunctionReturn(0);
115763602bcaSStefano Zampini }
115863602bcaSStefano Zampini 
115963602bcaSStefano Zampini /*@
116063602bcaSStefano Zampini  PCBDDCSetDofsSplittingLocal - Set index sets defining fields of the local subdomain matrix
116163602bcaSStefano Zampini 
116263602bcaSStefano Zampini    Collective
116363602bcaSStefano Zampini 
116463602bcaSStefano Zampini    Input Parameters:
116563602bcaSStefano Zampini +  pc - the preconditioning context
11660f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
11670f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in local ordering
116863602bcaSStefano Zampini 
116963602bcaSStefano Zampini    Level: intermediate
117063602bcaSStefano Zampini 
11710f202f7eSStefano Zampini    Notes:
11720f202f7eSStefano Zampini      n_is should be the same among processes. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
117363602bcaSStefano Zampini 
1174db781477SPatrick Sanan .seealso: `PCBDDC`
117563602bcaSStefano Zampini @*/
117663602bcaSStefano Zampini PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc,PetscInt n_is, IS ISForDofs[])
117763602bcaSStefano Zampini {
117863602bcaSStefano Zampini   PetscInt       i;
117963602bcaSStefano Zampini 
118063602bcaSStefano Zampini   PetscFunctionBegin;
118163602bcaSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
118263602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
118363602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
118463602bcaSStefano Zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
118563602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
118663602bcaSStefano Zampini   }
1187cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetDofsSplittingLocal_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));
118863602bcaSStefano Zampini   PetscFunctionReturn(0);
118963602bcaSStefano Zampini }
119063602bcaSStefano Zampini 
11919c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
11929c0446d6SStefano Zampini {
11939c0446d6SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
11949c0446d6SStefano Zampini   PetscInt       i;
119556282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
11969c0446d6SStefano Zampini 
11979c0446d6SStefano Zampini   PetscFunctionBegin;
119856282151SStefano Zampini   if (pcbddc->n_ISForDofs == n_is) {
119956282151SStefano Zampini     for (i=0;i<n_is;i++) {
120056282151SStefano Zampini       PetscBool isequalt;
12019566063dSJacob Faibussowitsch       PetscCall(ISEqual(ISForDofs[i],pcbddc->ISForDofs[i],&isequalt));
120256282151SStefano Zampini       if (!isequalt) break;
120356282151SStefano Zampini     }
120456282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
120556282151SStefano Zampini   }
120656282151SStefano Zampini   for (i=0;i<n_is;i++) {
12079566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)ISForDofs[i]));
120856282151SStefano Zampini   }
1209da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
12109c0446d6SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
12119566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&pcbddc->ISForDofs[i]));
12129c0446d6SStefano Zampini   }
12139566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofs));
1214a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
121563602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
12169566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i]));
121763602bcaSStefano Zampini   }
12189566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofsLocal));
121963602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = 0;
1220da1bb401SStefano Zampini   /* allocate space then set */
1221d02579f5SStefano Zampini   if (n_is) {
12229566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n_is,&pcbddc->ISForDofs));
1223d02579f5SStefano Zampini   }
12249c0446d6SStefano Zampini   for (i=0;i<n_is;i++) {
1225da1bb401SStefano Zampini     pcbddc->ISForDofs[i] = ISForDofs[i];
12269c0446d6SStefano Zampini   }
12279c0446d6SStefano Zampini   pcbddc->n_ISForDofs = n_is;
122863602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
122956282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
12309c0446d6SStefano Zampini   PetscFunctionReturn(0);
12319c0446d6SStefano Zampini }
12321e6b0712SBarry Smith 
12339c0446d6SStefano Zampini /*@
123463602bcaSStefano Zampini  PCBDDCSetDofsSplitting - Set index sets defining fields of the global matrix
12359c0446d6SStefano Zampini 
123663602bcaSStefano Zampini    Collective
12379c0446d6SStefano Zampini 
12389c0446d6SStefano Zampini    Input Parameters:
12399c0446d6SStefano Zampini +  pc - the preconditioning context
12400f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
12410f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in global ordering
12429c0446d6SStefano Zampini 
12439c0446d6SStefano Zampini    Level: intermediate
12449c0446d6SStefano Zampini 
12450f202f7eSStefano Zampini    Notes:
12460f202f7eSStefano Zampini      Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
12479c0446d6SStefano Zampini 
1248db781477SPatrick Sanan .seealso: `PCBDDC`
12499c0446d6SStefano Zampini @*/
12509c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
12519c0446d6SStefano Zampini {
12522b510759SStefano Zampini   PetscInt       i;
12539c0446d6SStefano Zampini 
12549c0446d6SStefano Zampini   PetscFunctionBegin;
12559c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
125663602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
12572b510759SStefano Zampini   for (i=0;i<n_is;i++) {
125863602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
1259a011d5a7Sstefano_zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
12602b510759SStefano Zampini   }
1261cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));
12629c0446d6SStefano Zampini   PetscFunctionReturn(0);
12639c0446d6SStefano Zampini }
1264906d46d4SStefano Zampini 
1265534831adSStefano Zampini /*
1266534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
1267534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
12689c0446d6SStefano Zampini 
1269534831adSStefano Zampini    Input Parameter:
1270966d8056SPierre Jolivet +  pc - the preconditioner context
1271534831adSStefano Zampini 
1272534831adSStefano Zampini    Application Interface Routine: PCPreSolve()
1273534831adSStefano Zampini 
1274534831adSStefano Zampini    Notes:
1275534831adSStefano Zampini      The interface routine PCPreSolve() is not usually called directly by
1276534831adSStefano Zampini    the user, but instead is called by KSPSolve().
1277534831adSStefano Zampini */
1278534831adSStefano Zampini static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1279534831adSStefano Zampini {
1280534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1281534831adSStefano Zampini   PC_IS          *pcis = (PC_IS*)(pc->data);
12823972b0daSStefano Zampini   Vec            used_vec;
1283fcb54b1cSPierre Jolivet   PetscBool      iscg, save_rhs = PETSC_TRUE, benign_correction_computed;
1284534831adSStefano Zampini 
1285534831adSStefano Zampini   PetscFunctionBegin;
12861f4df5f7SStefano Zampini   /* if we are working with CG, one dirichlet solve can be avoided during Krylov iterations */
128785c4d303SStefano Zampini   if (ksp) {
1288fcb54b1cSPierre Jolivet     PetscCall(PetscObjectTypeCompareAny((PetscObject)ksp,&iscg,KSPCG,KSPGROPPCG,KSPPIPECG,KSPPIPELCG,KSPPIPECGRR,""));
12893bf6e316SStefano Zampini     if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || !iscg || pc->mat != pc->pmat) {
12909566063dSJacob Faibussowitsch       PetscCall(PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE));
129185c4d303SStefano Zampini     }
129285c4d303SStefano Zampini   }
12933bf6e316SStefano Zampini   if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || pc->mat != pc->pmat) {
12949566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE));
1295fc17d649SStefano Zampini   }
12961f4df5f7SStefano Zampini 
129785c4d303SStefano Zampini   /* Creates parallel work vectors used in presolve */
129862a6ff1dSStefano Zampini   if (!pcbddc->original_rhs) {
12999566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs));
130062a6ff1dSStefano Zampini   }
130162a6ff1dSStefano Zampini   if (!pcbddc->temp_solution) {
13029566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution));
130362a6ff1dSStefano Zampini   }
13048d00608fSStefano Zampini 
130527b6a85dSStefano Zampini   pcbddc->temp_solution_used = PETSC_FALSE;
13063972b0daSStefano Zampini   if (x) {
13079566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)x));
13083972b0daSStefano Zampini     used_vec = x;
13098d00608fSStefano Zampini   } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */
13109566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pcbddc->temp_solution));
13113972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
13129566063dSJacob Faibussowitsch     PetscCall(VecSet(used_vec,0.0));
131327b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
13149566063dSJacob Faibussowitsch     PetscCall(VecCopy(rhs,pcbddc->original_rhs));
1315266e20e9SStefano Zampini     save_rhs = PETSC_FALSE;
1316266e20e9SStefano Zampini     pcbddc->eliminate_dirdofs = PETSC_TRUE;
13173972b0daSStefano Zampini   }
13188efcfb23SStefano Zampini 
13198efcfb23SStefano Zampini   /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */
13203972b0daSStefano Zampini   if (ksp) {
1321a0cb1b98SStefano Zampini     /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */
13229566063dSJacob Faibussowitsch     PetscCall(KSPGetInitialGuessNonzero(ksp,&pcbddc->ksp_guess_nonzero));
13238efcfb23SStefano Zampini     if (!pcbddc->ksp_guess_nonzero) {
13249566063dSJacob Faibussowitsch       PetscCall(VecSet(used_vec,0.0));
13253972b0daSStefano Zampini     }
13263972b0daSStefano Zampini   }
13273308cffdSStefano Zampini 
13288d00608fSStefano Zampini   pcbddc->rhs_change = PETSC_FALSE;
13293972b0daSStefano Zampini   /* Take into account zeroed rows -> change rhs and store solution removed */
133070c64980SStefano Zampini   if (rhs && pcbddc->eliminate_dirdofs) {
13313975b054SStefano Zampini     IS dirIS = NULL;
13323975b054SStefano Zampini 
1333a07ea27aSStefano Zampini     /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */
13349566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS));
13353975b054SStefano Zampini     if (dirIS) {
1336906d46d4SStefano Zampini       Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
1337785d1243SStefano Zampini       PetscInt          dirsize,i,*is_indices;
13382b095fd8SStefano Zampini       PetscScalar       *array_x;
13392b095fd8SStefano Zampini       const PetscScalar *array_diagonal;
1340785d1243SStefano Zampini 
13419566063dSJacob Faibussowitsch       PetscCall(MatGetDiagonal(pc->pmat,pcis->vec1_global));
13429566063dSJacob Faibussowitsch       PetscCall(VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global));
13439566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD));
13449566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD));
13459566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD));
13469566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD));
13479566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(dirIS,&dirsize));
13489566063dSJacob Faibussowitsch       PetscCall(VecGetArray(pcis->vec1_N,&array_x));
13499566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(pcis->vec2_N,&array_diagonal));
13509566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(dirIS,(const PetscInt**)&is_indices));
13512fa5cd67SKarl Rupp       for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
13529566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(dirIS,(const PetscInt**)&is_indices));
13539566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(pcis->vec2_N,&array_diagonal));
13549566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(pcis->vec1_N,&array_x));
13559566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE));
13569566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE));
13578d00608fSStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
13589566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&dirIS));
13598efcfb23SStefano Zampini     }
1360a07ea27aSStefano Zampini   }
1361b76ba322SStefano Zampini 
13628efcfb23SStefano Zampini   /* remove the computed solution or the initial guess from the rhs */
13638d00608fSStefano Zampini   if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero)) {
136427b6a85dSStefano Zampini     /* save the original rhs */
136527b6a85dSStefano Zampini     if (save_rhs) {
13669566063dSJacob Faibussowitsch       PetscCall(VecSwap(rhs,pcbddc->original_rhs));
136727b6a85dSStefano Zampini       save_rhs = PETSC_FALSE;
13688d00608fSStefano Zampini     }
13698d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
13709566063dSJacob Faibussowitsch     PetscCall(VecScale(used_vec,-1.0));
13719566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(pc->mat,used_vec,pcbddc->original_rhs,rhs));
13729566063dSJacob Faibussowitsch     PetscCall(VecScale(used_vec,-1.0));
13739566063dSJacob Faibussowitsch     PetscCall(VecCopy(used_vec,pcbddc->temp_solution));
137427b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
13751baa6e33SBarry Smith     if (ksp) PetscCall(KSPSetInitialGuessNonzero(ksp,PETSC_FALSE));
13763308cffdSStefano Zampini   }
13779566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&used_vec));
1378b76ba322SStefano Zampini 
1379fc17d649SStefano Zampini   /* compute initial vector in benign space if needed
138027b6a85dSStefano Zampini      and remove non-benign solution from the rhs */
138127b6a85dSStefano Zampini   benign_correction_computed = PETSC_FALSE;
138208af2428SStefano Zampini   if (rhs && pcbddc->benign_compute_correction && (pcbddc->benign_have_null || pcbddc->benign_apply_coarse_only)) {
13831f4df5f7SStefano Zampini     /* compute u^*_h using ideas similar to those in Xuemin Tu's PhD thesis (see Section 4.8.1)
13841f4df5f7SStefano Zampini        Recursively apply BDDC in the multilevel case */
13850369aaf7SStefano Zampini     if (!pcbddc->benign_vec) {
13869566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(rhs,&pcbddc->benign_vec));
13870369aaf7SStefano Zampini     }
1388c69e9cc1SStefano Zampini     /* keep applying coarse solver unless we no longer have benign subdomains */
1389c69e9cc1SStefano Zampini     pcbddc->benign_apply_coarse_only = pcbddc->benign_have_null ? PETSC_TRUE : PETSC_FALSE;
139027b6a85dSStefano Zampini     if (!pcbddc->benign_skip_correction) {
13919566063dSJacob Faibussowitsch       PetscCall(PCApply_BDDC(pc,rhs,pcbddc->benign_vec));
13923bca92a6SStefano Zampini       benign_correction_computed = PETSC_TRUE;
13931baa6e33SBarry Smith       if (pcbddc->temp_solution_used) PetscCall(VecAXPY(pcbddc->temp_solution,1.0,pcbddc->benign_vec));
13949566063dSJacob Faibussowitsch       PetscCall(VecScale(pcbddc->benign_vec,-1.0));
139527b6a85dSStefano Zampini       /* store the original rhs if not done earlier */
13961baa6e33SBarry Smith       if (save_rhs) PetscCall(VecSwap(rhs,pcbddc->original_rhs));
139727b6a85dSStefano Zampini       if (pcbddc->rhs_change) {
13989566063dSJacob Faibussowitsch         PetscCall(MatMultAdd(pc->mat,pcbddc->benign_vec,rhs,rhs));
139927b6a85dSStefano Zampini       } else {
14009566063dSJacob Faibussowitsch         PetscCall(MatMultAdd(pc->mat,pcbddc->benign_vec,pcbddc->original_rhs,rhs));
140127b6a85dSStefano Zampini       }
14020369aaf7SStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
140327b6a85dSStefano Zampini     }
140427b6a85dSStefano Zampini     pcbddc->benign_apply_coarse_only = PETSC_FALSE;
14054df7a6bfSStefano Zampini   } else {
14069566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&pcbddc->benign_vec));
14070369aaf7SStefano Zampini   }
14082d4c4fecSStefano Zampini 
14092d4c4fecSStefano Zampini   /* dbg output */
1410a198735bSStefano Zampini   if (pcbddc->dbg_flag && benign_correction_computed) {
14111f4df5f7SStefano Zampini     Vec v;
1412c69e9cc1SStefano Zampini 
14139566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_global,&v));
1414c69e9cc1SStefano Zampini     if (pcbddc->ChangeOfBasisMatrix) {
14159566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,v));
1416c69e9cc1SStefano Zampini     } else {
14179566063dSJacob Faibussowitsch       PetscCall(VecCopy(rhs,v));
1418c69e9cc1SStefano Zampini     }
14199566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc,v,PETSC_TRUE));
142063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"LEVEL %" PetscInt_FMT ": is the correction benign?\n",pcbddc->current_level));
14219566063dSJacob Faibussowitsch     PetscCall(PetscScalarView(pcbddc->benign_n,pcbddc->benign_p0,pcbddc->dbg_viewer));
14229566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
14239566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&v));
14241f4df5f7SStefano Zampini   }
14250369aaf7SStefano Zampini 
14260369aaf7SStefano Zampini   /* set initial guess if using PCG */
14278ae0ca82SStefano Zampini   pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
14280369aaf7SStefano Zampini   if (x && pcbddc->use_exact_dirichlet_trick) {
14299566063dSJacob Faibussowitsch     PetscCall(VecSet(x,0.0));
14301dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
143127b6a85dSStefano Zampini       if (benign_correction_computed) { /* we have already saved the changed rhs */
14329566063dSJacob Faibussowitsch         PetscCall(VecLockReadPop(pcis->vec1_global));
14331dd7afcfSStefano Zampini       } else {
14349566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,pcis->vec1_global));
14351dd7afcfSStefano Zampini       }
14369566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
14379566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
14381dd7afcfSStefano Zampini     } else {
14399566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
14409566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
14411dd7afcfSStefano Zampini     }
14429566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
14439566063dSJacob Faibussowitsch     PetscCall(KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D));
14449566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
14459566063dSJacob Faibussowitsch     PetscCall(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D));
14461dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
14479566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_global,0.));
14489566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE));
14499566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE));
14509566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x));
14511dd7afcfSStefano Zampini     } else {
14529566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE));
14539566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE));
14541dd7afcfSStefano Zampini     }
14551baa6e33SBarry Smith     if (ksp) PetscCall(KSPSetInitialGuessNonzero(ksp,PETSC_TRUE));
14568ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_TRUE;
1457266e20e9SStefano Zampini   } else if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior && benign_correction_computed && pcbddc->use_exact_dirichlet_trick) {
14589566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(pcis->vec1_global));
14590369aaf7SStefano Zampini   }
1460534831adSStefano Zampini   PetscFunctionReturn(0);
1461534831adSStefano Zampini }
1462906d46d4SStefano Zampini 
1463534831adSStefano Zampini /*
1464534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
1465534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
1466534831adSStefano Zampini 
1467534831adSStefano Zampini    Input Parameter:
1468966d8056SPierre Jolivet +  pc - the preconditioner context
1469534831adSStefano Zampini 
1470534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
1471534831adSStefano Zampini 
1472534831adSStefano Zampini    Notes:
1473534831adSStefano Zampini      The interface routine PCPostSolve() is not usually called directly by
1474534831adSStefano Zampini      the user, but instead is called by KSPSolve().
1475534831adSStefano Zampini */
1476534831adSStefano Zampini static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1477534831adSStefano Zampini {
1478534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1479534831adSStefano Zampini 
1480534831adSStefano Zampini   PetscFunctionBegin;
14813972b0daSStefano Zampini   /* add solution removed in presolve */
14826bcfc461SStefano Zampini   if (x && pcbddc->rhs_change) {
148327b6a85dSStefano Zampini     if (pcbddc->temp_solution_used) {
14849566063dSJacob Faibussowitsch       PetscCall(VecAXPY(x,1.0,pcbddc->temp_solution));
1485af140850Sstefano_zampini     } else if (pcbddc->benign_compute_correction && pcbddc->benign_vec) {
14869566063dSJacob Faibussowitsch       PetscCall(VecAXPY(x,-1.0,pcbddc->benign_vec));
14873425bc38SStefano Zampini     }
1488af140850Sstefano_zampini     /* restore to original state (not for FETI-DP) */
1489af140850Sstefano_zampini     if (ksp) pcbddc->temp_solution_used = PETSC_FALSE;
149027b6a85dSStefano Zampini   }
149127b6a85dSStefano Zampini 
1492266e20e9SStefano Zampini   /* restore rhs to its original state (not needed for FETI-DP) */
14938d00608fSStefano Zampini   if (rhs && pcbddc->rhs_change) {
14949566063dSJacob Faibussowitsch     PetscCall(VecSwap(rhs,pcbddc->original_rhs));
14958d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_FALSE;
1496af140850Sstefano_zampini   }
14978efcfb23SStefano Zampini   /* restore ksp guess state */
14988efcfb23SStefano Zampini   if (ksp) {
14999566063dSJacob Faibussowitsch     PetscCall(KSPSetInitialGuessNonzero(ksp,pcbddc->ksp_guess_nonzero));
15008ae0ca82SStefano Zampini     /* reset flag for exact dirichlet trick */
15018ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
1502af140850Sstefano_zampini   }
1503534831adSStefano Zampini   PetscFunctionReturn(0);
1504534831adSStefano Zampini }
1505af140850Sstefano_zampini 
15060c7d97c5SJed Brown /*
15070c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
15080c7d97c5SJed Brown                   by setting data structures and options.
15090c7d97c5SJed Brown 
15100c7d97c5SJed Brown    Input Parameter:
151153cdbc3dSStefano Zampini +  pc - the preconditioner context
15120c7d97c5SJed Brown 
15130c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
15140c7d97c5SJed Brown 
15150c7d97c5SJed Brown    Notes:
15160c7d97c5SJed Brown      The interface routine PCSetUp() is not usually called directly by
15170c7d97c5SJed Brown      the user, but instead is called by PCApply() if necessary.
15180c7d97c5SJed Brown */
151953cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
15200c7d97c5SJed Brown {
15210c7d97c5SJed Brown   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1522c703fcc7SStefano Zampini   PCBDDCSubSchurs sub_schurs;
15235e8657edSStefano Zampini   Mat_IS*         matis;
152408122e43SStefano Zampini   MatNullSpace    nearnullspace;
152535509ce9Sstefano_zampini   Mat             lA;
152635509ce9Sstefano_zampini   IS              lP,zerodiag = NULL;
152791e8d312SStefano Zampini   PetscInt        nrows,ncols;
152886bfa4cfSStefano Zampini   PetscMPIInt     size;
1529c703fcc7SStefano Zampini   PetscBool       computesubschurs;
15308de1fae6SStefano Zampini   PetscBool       computeconstraintsmatrix;
15313b03f7bbSStefano Zampini   PetscBool       new_nearnullspace_provided,ismatis,rl;
1532*b94d7dedSBarry Smith   PetscBool       isset,issym,isspd;
15330c7d97c5SJed Brown 
15340c7d97c5SJed Brown   PetscFunctionBegin;
15359566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat,MATIS,&ismatis));
153628b400f6SJacob Faibussowitsch   PetscCheck(ismatis,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner requires matrix of type MATIS");
15379566063dSJacob Faibussowitsch   PetscCall(MatGetSize(pc->pmat,&nrows,&ncols));
15387827d75bSBarry Smith   PetscCheck(nrows == ncols,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCBDDC preconditioner requires a square preconditioning matrix");
15399566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size));
154086bfa4cfSStefano Zampini 
15415e8657edSStefano Zampini   matis = (Mat_IS*)pc->pmat->data;
1542f4ddd8eeSStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */
15433b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
154471582508SStefano Zampini      Also, BDDC builds its own KSP for the Dirichlet problem */
15453b03f7bbSStefano Zampini   rl = pcbddc->recompute_topography;
15463b03f7bbSStefano Zampini   if (!pc->setupcalled || pc->flag == DIFFERENT_NONZERO_PATTERN) rl = PETSC_TRUE;
15471c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&rl,&pcbddc->recompute_topography,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc)));
1548c83e1ba7SStefano Zampini   if (pcbddc->recompute_topography) {
1549c83e1ba7SStefano Zampini     pcbddc->graphanalyzed    = PETSC_FALSE;
1550c83e1ba7SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1551c83e1ba7SStefano Zampini   } else {
15528de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_FALSE;
1553c83e1ba7SStefano Zampini   }
1554b087196eSStefano Zampini 
1555b087196eSStefano Zampini   /* check parameters' compatibility */
1556b7ab4a40SStefano Zampini   if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE;
1557bd2a564bSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_threshold[0] != 0.0 || pcbddc->adaptive_threshold[1] != 0.0);
155886bfa4cfSStefano Zampini   pcbddc->use_deluxe_scaling   = (PetscBool)(pcbddc->use_deluxe_scaling && size > 1);
155986bfa4cfSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_selection && size > 1);
1560bf3a8328SStefano Zampini   pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined);
1561862806e4SStefano Zampini   if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE;
1562862806e4SStefano Zampini 
15635a95e1ceSStefano Zampini   computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling);
156416909a7fSStefano Zampini 
156571582508SStefano Zampini   /* activate all connected components if the netflux has been requested */
1566bb05f991SStefano Zampini   if (pcbddc->compute_nonetflux) {
1567bb05f991SStefano Zampini     pcbddc->use_vertices = PETSC_TRUE;
1568bb05f991SStefano Zampini     pcbddc->use_edges    = PETSC_TRUE;
1569bb05f991SStefano Zampini     pcbddc->use_faces    = PETSC_TRUE;
1570bb05f991SStefano Zampini   }
1571bb05f991SStefano Zampini 
1572f4ddd8eeSStefano Zampini   /* Get stdout for dbg */
157370cf5478SStefano Zampini   if (pcbddc->dbg_flag) {
157470cf5478SStefano Zampini     if (!pcbddc->dbg_viewer) {
157558a03d70SStefano Zampini       pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc));
1576f4ddd8eeSStefano Zampini     }
15779566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer));
15789566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2*pcbddc->current_level));
1579f4ddd8eeSStefano Zampini   }
1580f4ddd8eeSStefano Zampini 
1581c703fcc7SStefano Zampini   /* process topology information */
15829566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Topology[pcbddc->current_level],pc,0,0,0));
158371582508SStefano Zampini   if (pcbddc->recompute_topography) {
15849566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeLocalTopologyInfo(pc));
15851baa6e33SBarry Smith     if (pcbddc->discretegradient) PetscCall(PCBDDCNedelecSupport(pc));
1586c703fcc7SStefano Zampini   }
15874f819b78SStefano Zampini   if (pcbddc->corner_selected) pcbddc->use_vertices = PETSC_TRUE;
1588a13144ffSStefano Zampini 
1589c703fcc7SStefano Zampini   /* change basis if requested by the user */
15905e8657edSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) {
15915e8657edSStefano Zampini     /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */
15925e8657edSStefano Zampini     pcbddc->use_change_of_basis = PETSC_FALSE;
15939566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeLocalMatrix(pc,pcbddc->user_ChangeOfBasisMatrix));
15945e8657edSStefano Zampini   } else {
15959566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcbddc->local_mat));
15969566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)matis->A));
15975e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
1598d16cbb6bSStefano Zampini   }
1599d16cbb6bSStefano Zampini 
16004f1b2e48SStefano Zampini   /*
1601c703fcc7SStefano Zampini      Compute change of basis on local pressures (aka zerodiag dofs) with the benign trick
16024f1b2e48SStefano Zampini      This should come earlier then PCISSetUp for extracting the correct subdomain matrices
16034f1b2e48SStefano Zampini   */
16049566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignShellMat(pc,PETSC_TRUE));
1605d16cbb6bSStefano Zampini   if (pcbddc->benign_saddle_point) {
16069f47a83aSStefano Zampini     PC_IS* pcis = (PC_IS*)pc->data;
16079f47a83aSStefano Zampini 
160805b28244SStefano Zampini     if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE;
16093b03f7bbSStefano Zampini     /* detect local saddle point and change the basis in pcbddc->local_mat */
16109566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignDetectSaddlePoint(pc,(PetscBool)(!pcbddc->recompute_topography),&zerodiag));
1611a3df083aSStefano Zampini     /* pop B0 mat from local mat */
16129566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE));
16131dd7afcfSStefano Zampini     /* give pcis a hint to not reuse submatrices during PCISCreate */
16141dd7afcfSStefano Zampini     if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) {
16151dd7afcfSStefano Zampini       if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) {
16161dd7afcfSStefano Zampini         pcis->reusesubmatrices = PETSC_FALSE;
16171dd7afcfSStefano Zampini       } else {
1618a3df083aSStefano Zampini         pcis->reusesubmatrices = PETSC_TRUE;
16191dd7afcfSStefano Zampini       }
1620a3df083aSStefano Zampini     } else {
16219f47a83aSStefano Zampini       pcis->reusesubmatrices = PETSC_FALSE;
1622674ae819SStefano Zampini     }
1623a3df083aSStefano Zampini   }
162427b6a85dSStefano Zampini 
16258037d520SStefano Zampini   /* propagate relevant information */
1626*b94d7dedSBarry Smith   PetscCall(MatIsSymmetricKnown(matis->A,&isset,&issym));
1627*b94d7dedSBarry Smith   if (isset) PetscCall(MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,issym));
1628*b94d7dedSBarry Smith   PetscCall(MatIsSPDKnown(matis->A,&isset,&isspd));
1629*b94d7dedSBarry Smith   if (isset) PetscCall(MatSetOption(pcbddc->local_mat,MAT_SPD,isspd));
1630e496cd5dSStefano Zampini 
16315e8657edSStefano Zampini   /* Set up all the "iterative substructuring" common block without computing solvers */
16325e8657edSStefano Zampini   {
16335e8657edSStefano Zampini     Mat temp_mat;
16345e8657edSStefano Zampini 
16355e8657edSStefano Zampini     temp_mat = matis->A;
16365e8657edSStefano Zampini     matis->A = pcbddc->local_mat;
16379566063dSJacob Faibussowitsch     PetscCall(PCISSetUp(pc,PETSC_TRUE,PETSC_FALSE));
16385e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
16395e8657edSStefano Zampini     matis->A = temp_mat;
16405e8657edSStefano Zampini   }
1641684f6988SStefano Zampini 
164281d14e9dSStefano Zampini   /* Analyze interface */
164364ac59b8SStefano Zampini   if (!pcbddc->graphanalyzed) {
16449566063dSJacob Faibussowitsch     PetscCall(PCBDDCAnalyzeInterface(pc));
16458de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1646345ecf6cSStefano Zampini     if (pcbddc->adaptive_selection && !pcbddc->use_deluxe_scaling && !pcbddc->mat_graph->twodim) {
16474247aa23Sstefano_zampini       SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot compute the adaptive primal space for a problem with 3D edges without deluxe scaling");
1648345ecf6cSStefano Zampini     }
1649a198735bSStefano Zampini     if (pcbddc->compute_nonetflux) {
1650669cc0f4SStefano Zampini       MatNullSpace nnfnnsp;
1651669cc0f4SStefano Zampini 
165228b400f6SJacob Faibussowitsch       PetscCheck(pcbddc->divudotp,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Missing divudotp operator");
16539566063dSJacob Faibussowitsch       PetscCall(PCBDDCComputeNoNetFlux(pc->pmat,pcbddc->divudotp,pcbddc->divudotp_trans,pcbddc->divudotp_vl2l,pcbddc->mat_graph,&nnfnnsp));
165471582508SStefano Zampini       /* TODO what if a nearnullspace is already attached? */
16558037d520SStefano Zampini       if (nnfnnsp) {
16569566063dSJacob Faibussowitsch         PetscCall(MatSetNearNullSpace(pc->pmat,nnfnnsp));
16579566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceDestroy(&nnfnnsp));
1658669cc0f4SStefano Zampini       }
1659674ae819SStefano Zampini     }
16608037d520SStefano Zampini   }
16619566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Topology[pcbddc->current_level],pc,0,0,0));
1662fb8d54d4SStefano Zampini 
16635408967cSStefano Zampini   /* check existence of a divergence free extension, i.e.
16645408967cSStefano Zampini      b(v_I,p_0) = 0 for all v_I (raise error if not).
16655408967cSStefano Zampini      Also, check that PCBDDCBenignGetOrSetP0 works */
1666ff1f7e73Sstefano_zampini   if (pcbddc->benign_saddle_point && pcbddc->dbg_flag > 1) {
16679566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignCheck(pc,zerodiag));
166809f581a4SStefano Zampini   }
16699566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&zerodiag));
167006f24817SStefano Zampini 
1671b96c3477SStefano Zampini   /* Setup local dirichlet solver ksp_D and sub_schurs solvers */
1672c703fcc7SStefano Zampini   if (computesubschurs && pcbddc->recompute_topography) {
16739566063dSJacob Faibussowitsch     PetscCall(PCBDDCInitSubSchurs(pc));
1674b1b3d7a2SStefano Zampini   }
16759d54b7f4SStefano Zampini   /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/
16769d54b7f4SStefano Zampini   if (!pcbddc->use_deluxe_scaling) {
16779566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingSetUp(pc));
16789d54b7f4SStefano Zampini   }
1679c703fcc7SStefano Zampini 
1680c703fcc7SStefano Zampini   /* finish setup solvers and do adaptive selection of constraints */
1681b334f244SStefano Zampini   sub_schurs = pcbddc->sub_schurs;
1682b334f244SStefano Zampini   if (sub_schurs && sub_schurs->schur_explicit) {
16831baa6e33SBarry Smith     if (computesubschurs) PetscCall(PCBDDCSetUpSubSchurs(pc));
16849566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE));
1685d5574798SStefano Zampini   } else {
16869566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE));
16871baa6e33SBarry Smith     if (computesubschurs) PetscCall(PCBDDCSetUpSubSchurs(pc));
16882070dbb6SStefano Zampini   }
168908122e43SStefano Zampini   if (pcbddc->adaptive_selection) {
16909566063dSJacob Faibussowitsch     PetscCall(PCBDDCAdaptiveSelection(pc));
16918de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1692b7eb3628SStefano Zampini   }
1693684f6988SStefano Zampini 
1694f4ddd8eeSStefano Zampini   /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */
1695fb8d54d4SStefano Zampini   new_nearnullspace_provided = PETSC_FALSE;
16969566063dSJacob Faibussowitsch   PetscCall(MatGetNearNullSpace(pc->pmat,&nearnullspace));
1697f4ddd8eeSStefano Zampini   if (pcbddc->onearnullspace) { /* already used nearnullspace */
1698f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* near null space attached to mat has been destroyed */
1699f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1700f4ddd8eeSStefano Zampini     } else {
1701f4ddd8eeSStefano Zampini       /* determine if the two nullspaces are different (should be lightweight) */
1702f4ddd8eeSStefano Zampini       if (nearnullspace != pcbddc->onearnullspace) {
1703f4ddd8eeSStefano Zampini         new_nearnullspace_provided = PETSC_TRUE;
1704165b64e2SStefano Zampini       } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */
1705f4ddd8eeSStefano Zampini         PetscInt         i;
1706165b64e2SStefano Zampini         const Vec        *nearnullvecs;
1707165b64e2SStefano Zampini         PetscObjectState state;
1708165b64e2SStefano Zampini         PetscInt         nnsp_size;
17099566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceGetVecs(nearnullspace,NULL,&nnsp_size,&nearnullvecs));
1710f4ddd8eeSStefano Zampini         for (i=0;i<nnsp_size;i++) {
17119566063dSJacob Faibussowitsch           PetscCall(PetscObjectStateGet((PetscObject)nearnullvecs[i],&state));
1712165b64e2SStefano Zampini           if (pcbddc->onearnullvecs_state[i] != state) {
1713f4ddd8eeSStefano Zampini             new_nearnullspace_provided = PETSC_TRUE;
1714f4ddd8eeSStefano Zampini             break;
1715f4ddd8eeSStefano Zampini           }
1716f4ddd8eeSStefano Zampini         }
1717f4ddd8eeSStefano Zampini       }
1718f4ddd8eeSStefano Zampini     }
1719f4ddd8eeSStefano Zampini   } else {
1720f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* both nearnullspaces are null */
1721f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_FALSE;
1722f4ddd8eeSStefano Zampini     } else { /* nearnullspace attached later */
1723f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1724f4ddd8eeSStefano Zampini     }
1725f4ddd8eeSStefano Zampini   }
1726f4ddd8eeSStefano Zampini 
1727f4ddd8eeSStefano Zampini   /* Setup constraints and related work vectors */
1728727cdba6SStefano Zampini   /* reset primal space flags */
17299566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_LocalWork[pcbddc->current_level],pc,0,0,0));
1730f4ddd8eeSStefano Zampini   pcbddc->new_primal_space = PETSC_FALSE;
1731727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_FALSE;
17328de1fae6SStefano Zampini   if (computeconstraintsmatrix || new_nearnullspace_provided) {
1733727cdba6SStefano Zampini     /* It also sets the primal space flags */
17349566063dSJacob Faibussowitsch     PetscCall(PCBDDCConstraintsSetUp(pc));
17359543d0ffSStefano Zampini   }
1736e7b262bdSStefano Zampini   /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */
17379566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetUpLocalWorkVectors(pc));
17385e8657edSStefano Zampini 
17395e8657edSStefano Zampini   if (pcbddc->use_change_of_basis) {
17405e8657edSStefano Zampini     PC_IS *pcis = (PC_IS*)(pc->data);
17415e8657edSStefano Zampini 
17429566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeLocalMatrix(pc,pcbddc->ChangeOfBasisMatrix));
17434f1b2e48SStefano Zampini     if (pcbddc->benign_change) {
17449566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcbddc->benign_B0));
1745c263805aSStefano Zampini       /* pop B0 from pcbddc->local_mat */
17469566063dSJacob Faibussowitsch       PetscCall(PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE));
1747c263805aSStefano Zampini     }
17485e8657edSStefano Zampini     /* get submatrices */
17499566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_IB));
17509566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_BI));
17519566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_BB));
17529566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB));
17539566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB));
17549566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI));
17553975b054SStefano Zampini     /* set flag in pcis to not reuse submatrices during PCISCreate */
17563975b054SStefano Zampini     pcis->reusesubmatrices = PETSC_FALSE;
17579c6a02ceSStefano Zampini   } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) {
17589566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcbddc->local_mat));
17599566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)matis->A));
17605e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
17615e8657edSStefano Zampini   }
176235509ce9Sstefano_zampini 
176335509ce9Sstefano_zampini   /* interface pressure block row for B_C */
17649566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP" ,(PetscObject*)&lP));
17659566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA));
176635509ce9Sstefano_zampini   if (lA && lP) {
176735509ce9Sstefano_zampini     PC_IS*    pcis = (PC_IS*)pc->data;
176835509ce9Sstefano_zampini     Mat       B_BI,B_BB,Bt_BI,Bt_BB;
176935509ce9Sstefano_zampini     PetscBool issym;
1770*b94d7dedSBarry Smith 
17719566063dSJacob Faibussowitsch     PetscCall(MatIsSymmetric(lA,PETSC_SMALL,&issym));
17726cc1294bSstefano_zampini     if (issym) {
17739566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI));
17749566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB));
17759566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(B_BI,&Bt_BI));
17769566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(B_BB,&Bt_BB));
177735509ce9Sstefano_zampini     } else {
17789566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI));
17799566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB));
17809566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA,pcis->is_I_local,lP,MAT_INITIAL_MATRIX,&Bt_BI));
17819566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA,pcis->is_B_local,lP,MAT_INITIAL_MATRIX,&Bt_BB));
178235509ce9Sstefano_zampini     }
17839566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BI",(PetscObject)B_BI));
17849566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BB",(PetscObject)B_BB));
17859566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BI",(PetscObject)Bt_BI));
17869566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BB",(PetscObject)Bt_BB));
17879566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B_BI));
17889566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B_BB));
17899566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Bt_BI));
17909566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Bt_BB));
179135509ce9Sstefano_zampini   }
17929566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_LocalWork[pcbddc->current_level],pc,0,0,0));
179335509ce9Sstefano_zampini 
1794b96c3477SStefano Zampini   /* SetUp coarse and local Neumann solvers */
17959566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetUpSolvers(pc));
1796b96c3477SStefano Zampini   /* SetUp Scaling operator */
17971baa6e33SBarry Smith   if (pcbddc->use_deluxe_scaling) PetscCall(PCBDDCScalingSetUp(pc));
1798c703fcc7SStefano Zampini 
17991dd7afcfSStefano Zampini   /* mark topography as done */
180056282151SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
18010369aaf7SStefano Zampini 
18021dd7afcfSStefano Zampini   /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */
18039566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignShellMat(pc,PETSC_FALSE));
18041dd7afcfSStefano Zampini 
180558a03d70SStefano Zampini   if (pcbddc->dbg_flag) {
18069566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2*pcbddc->current_level));
18079566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer));
18082b510759SStefano Zampini   }
18090c7d97c5SJed Brown   PetscFunctionReturn(0);
18100c7d97c5SJed Brown }
18110c7d97c5SJed Brown 
18120c7d97c5SJed Brown /*
181350efa1b5SStefano Zampini    PCApply_BDDC - Applies the BDDC operator to a vector.
18140c7d97c5SJed Brown 
18150c7d97c5SJed Brown    Input Parameters:
18160f202f7eSStefano Zampini +  pc - the preconditioner context
18170f202f7eSStefano Zampini -  r - input vector (global)
18180c7d97c5SJed Brown 
18190c7d97c5SJed Brown    Output Parameter:
18200c7d97c5SJed Brown .  z - output vector (global)
18210c7d97c5SJed Brown 
18220c7d97c5SJed Brown    Application Interface Routine: PCApply()
18230c7d97c5SJed Brown  */
182453cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
18250c7d97c5SJed Brown {
18260c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
18270c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1828b3338236SStefano Zampini   Mat               lA = NULL;
1829b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
18303b03a366Sstefano_zampini   const PetscScalar one = 1.0;
18313b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
18322617d88aSStefano Zampini   const PetscScalar zero = 0.0;
18330c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
18340c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
1835b097fa66SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */
18360c7d97c5SJed Brown 
18370c7d97c5SJed Brown   PetscFunctionBegin;
18389566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(citation,&cited));
1839b3338236SStefano Zampini   if (pcbddc->switch_static) {
18409566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat,&lA));
1841b3338236SStefano Zampini   }
1842b3338236SStefano Zampini 
18431dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
18441dd7afcfSStefano Zampini     Vec swap;
184527b6a85dSStefano Zampini 
18469566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change));
18471dd7afcfSStefano Zampini     swap = pcbddc->work_change;
18481dd7afcfSStefano Zampini     pcbddc->work_change = r;
18491dd7afcfSStefano Zampini     r = swap;
18501dd7afcfSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
18519cc2a9b1Sstefano_zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) {
18529566063dSJacob Faibussowitsch       PetscCall(VecCopy(r,pcis->vec1_global));
18539566063dSJacob Faibussowitsch       PetscCall(VecLockReadPush(pcis->vec1_global));
18541dd7afcfSStefano Zampini     }
18551dd7afcfSStefano Zampini   }
185627b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
18579566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE));
1858efc2fbd9SStefano Zampini   }
1859bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET && !pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
18609566063dSJacob Faibussowitsch     PetscCall(VecCopy(r,z));
18610c7d97c5SJed Brown     /* First Dirichlet solve */
18629566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
18639566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
18640c7d97c5SJed Brown     /*
18650c7d97c5SJed Brown       Assembling right hand side for BDDC operator
1866b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
1867674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
18680c7d97c5SJed Brown     */
1869b097fa66SStefano Zampini     if (n_D) {
18709566063dSJacob Faibussowitsch       PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
18719566063dSJacob Faibussowitsch       PetscCall(KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D));
18729566063dSJacob Faibussowitsch       PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
18739566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D));
18749566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec2_D,m_one));
187516909a7fSStefano Zampini       if (pcbddc->switch_static) {
18769566063dSJacob Faibussowitsch         PetscCall(VecSet(pcis->vec1_N,0.));
18779566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
18789566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
187916909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
18809566063dSJacob Faibussowitsch           PetscCall(MatMult(lA,pcis->vec1_N,pcis->vec2_N));
188116909a7fSStefano Zampini         } else {
18829566063dSJacob Faibussowitsch           PetscCall(MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N));
18839566063dSJacob Faibussowitsch           PetscCall(MatMult(lA,pcis->vec2_N,pcis->vec1_N));
18849566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N));
188516909a7fSStefano Zampini         }
18869566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD));
18879566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD));
18889566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
18899566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
189016909a7fSStefano Zampini       } else {
18919566063dSJacob Faibussowitsch         PetscCall(MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B));
189216909a7fSStefano Zampini       }
1893b097fa66SStefano Zampini     } else {
18949566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_B,zero));
1895b097fa66SStefano Zampini     }
18969566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE));
18979566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE));
18989566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingRestriction(pc,z,pcis->vec1_B));
1899b76ba322SStefano Zampini   } else {
19004fee134fSStefano Zampini     if (!pcbddc->benign_apply_coarse_only) {
19019566063dSJacob Faibussowitsch       PetscCall(PCBDDCScalingRestriction(pc,r,pcis->vec1_B));
1902b76ba322SStefano Zampini     }
19034fee134fSStefano Zampini   }
1904bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) {
190528b400f6SJacob Faibussowitsch     PetscCheck(pcbddc->switch_static,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"You forgot to pass -pc_bddc_switch_static");
19069566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
19079566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
1908bc960bbfSJed Brown   }
1909b76ba322SStefano Zampini 
19102617d88aSStefano Zampini   /* Apply interface preconditioner
19112617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
19129566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE));
19132617d88aSStefano Zampini 
1914674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
19159566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(pc,pcis->vec1_B,z));
1916bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) {
19179566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec1_D,z,INSERT_VALUES,SCATTER_REVERSE));
19189566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec1_D,z,INSERT_VALUES,SCATTER_REVERSE));
1919bc960bbfSJed Brown     PetscFunctionReturn(0);
1920bc960bbfSJed Brown   }
19213b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
19229566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
19239566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
1924b097fa66SStefano Zampini   if (n_B) {
192516909a7fSStefano Zampini     if (pcbddc->switch_static) {
19269566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
19279566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
19289566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
19299566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
193016909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
19319566063dSJacob Faibussowitsch         PetscCall(MatMult(lA,pcis->vec1_N,pcis->vec2_N));
193216909a7fSStefano Zampini       } else {
19339566063dSJacob Faibussowitsch         PetscCall(MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N));
19349566063dSJacob Faibussowitsch         PetscCall(MatMult(lA,pcis->vec2_N,pcis->vec1_N));
19359566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N));
193616909a7fSStefano Zampini       }
19379566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD));
19389566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD));
193916909a7fSStefano Zampini     } else {
19409566063dSJacob Faibussowitsch       PetscCall(MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D));
194116909a7fSStefano Zampini     }
194216909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
194316909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
19449566063dSJacob Faibussowitsch       PetscCall(MatMult(lA,pcis->vec1_D,pcis->vec3_D));
194516909a7fSStefano Zampini     } else {
19469566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N));
19479566063dSJacob Faibussowitsch       PetscCall(MatMult(lA,pcis->vec1_N,pcis->vec2_N));
19489566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D));
194916909a7fSStefano Zampini     }
1950b097fa66SStefano Zampini   }
19519566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
19529566063dSJacob Faibussowitsch   PetscCall(KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D));
19539566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
19549566063dSJacob Faibussowitsch   PetscCall(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec4_D));
1955efc2fbd9SStefano Zampini 
19568ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1957b097fa66SStefano Zampini     if (pcbddc->switch_static) {
19589566063dSJacob Faibussowitsch       PetscCall(VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D));
1959b097fa66SStefano Zampini     } else {
19609566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D));
1961b097fa66SStefano Zampini     }
19629566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE));
19639566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE));
1964b097fa66SStefano Zampini   } else {
1965b097fa66SStefano Zampini     if (pcbddc->switch_static) {
19669566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D));
1967b097fa66SStefano Zampini     } else {
19689566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec4_D,m_one));
1969b097fa66SStefano Zampini     }
19709566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE));
19719566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE));
1972b097fa66SStefano Zampini   }
197327b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
19741baa6e33SBarry Smith     if (pcbddc->benign_apply_coarse_only) PetscCall(PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n));
19759566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE));
1976efc2fbd9SStefano Zampini   }
19771f4df5f7SStefano Zampini 
19781dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1979f913dca9SStefano Zampini     pcbddc->work_change = r;
19809566063dSJacob Faibussowitsch     PetscCall(VecCopy(z,pcbddc->work_change));
19819566063dSJacob Faibussowitsch     PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z));
19821dd7afcfSStefano Zampini   }
19830c7d97c5SJed Brown   PetscFunctionReturn(0);
19840c7d97c5SJed Brown }
198550efa1b5SStefano Zampini 
198650efa1b5SStefano Zampini /*
198750efa1b5SStefano Zampini    PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector.
198850efa1b5SStefano Zampini 
198950efa1b5SStefano Zampini    Input Parameters:
19900f202f7eSStefano Zampini +  pc - the preconditioner context
19910f202f7eSStefano Zampini -  r - input vector (global)
199250efa1b5SStefano Zampini 
199350efa1b5SStefano Zampini    Output Parameter:
199450efa1b5SStefano Zampini .  z - output vector (global)
199550efa1b5SStefano Zampini 
199650efa1b5SStefano Zampini    Application Interface Routine: PCApplyTranspose()
199750efa1b5SStefano Zampini  */
199850efa1b5SStefano Zampini PetscErrorCode PCApplyTranspose_BDDC(PC pc,Vec r,Vec z)
199950efa1b5SStefano Zampini {
200050efa1b5SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
200150efa1b5SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
2002b3338236SStefano Zampini   Mat               lA = NULL;
2003b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
200450efa1b5SStefano Zampini   const PetscScalar one = 1.0;
200550efa1b5SStefano Zampini   const PetscScalar m_one = -1.0;
200650efa1b5SStefano Zampini   const PetscScalar zero = 0.0;
200750efa1b5SStefano Zampini 
200850efa1b5SStefano Zampini   PetscFunctionBegin;
20099566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(citation,&cited));
2010b3338236SStefano Zampini   if (pcbddc->switch_static) {
20119566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat,&lA));
2012b3338236SStefano Zampini   }
20131dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
20141dd7afcfSStefano Zampini     Vec swap;
201527b6a85dSStefano Zampini 
20169566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change));
20171dd7afcfSStefano Zampini     swap = pcbddc->work_change;
20181dd7afcfSStefano Zampini     pcbddc->work_change = r;
20191dd7afcfSStefano Zampini     r = swap;
202027b6a85dSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
20218ae0ca82SStefano Zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->exact_dirichlet_trick_app && pcbddc->change_interior) {
20229566063dSJacob Faibussowitsch       PetscCall(VecCopy(r,pcis->vec1_global));
20239566063dSJacob Faibussowitsch       PetscCall(VecLockReadPush(pcis->vec1_global));
20241dd7afcfSStefano Zampini     }
202527b6a85dSStefano Zampini   }
202627b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
20279566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE));
2028537c1cdfSStefano Zampini   }
20298ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
20309566063dSJacob Faibussowitsch     PetscCall(VecCopy(r,z));
203150efa1b5SStefano Zampini     /* First Dirichlet solve */
20329566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
20339566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
203450efa1b5SStefano Zampini     /*
203550efa1b5SStefano Zampini       Assembling right hand side for BDDC operator
2036b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
203750efa1b5SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
203850efa1b5SStefano Zampini     */
2039b097fa66SStefano Zampini     if (n_D) {
20409566063dSJacob Faibussowitsch       PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
20419566063dSJacob Faibussowitsch       PetscCall(KSPSolveTranspose(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D));
20429566063dSJacob Faibussowitsch       PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
20439566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D));
20449566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec2_D,m_one));
204516909a7fSStefano Zampini       if (pcbddc->switch_static) {
20469566063dSJacob Faibussowitsch         PetscCall(VecSet(pcis->vec1_N,0.));
20479566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
20489566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
204916909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
20509566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N));
205116909a7fSStefano Zampini         } else {
20529566063dSJacob Faibussowitsch           PetscCall(MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N));
20539566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(lA,pcis->vec2_N,pcis->vec1_N));
20549566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N));
205516909a7fSStefano Zampini         }
20569566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD));
20579566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD));
20589566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
20599566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
206016909a7fSStefano Zampini       } else {
20619566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcis->A_IB,pcis->vec2_D,pcis->vec1_B));
206216909a7fSStefano Zampini       }
2063b097fa66SStefano Zampini     } else {
20649566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_B,zero));
2065b097fa66SStefano Zampini     }
20669566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE));
20679566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE));
20689566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingRestriction(pc,z,pcis->vec1_B));
206950efa1b5SStefano Zampini   } else {
20709566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingRestriction(pc,r,pcis->vec1_B));
207150efa1b5SStefano Zampini   }
207250efa1b5SStefano Zampini 
207350efa1b5SStefano Zampini   /* Apply interface preconditioner
207450efa1b5SStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
20759566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(pc,PETSC_TRUE));
207650efa1b5SStefano Zampini 
207750efa1b5SStefano Zampini   /* Apply transpose of partition of unity operator */
20789566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(pc,pcis->vec1_B,z));
207950efa1b5SStefano Zampini 
208050efa1b5SStefano Zampini   /* Second Dirichlet solve and assembling of output */
20819566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
20829566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
2083b097fa66SStefano Zampini   if (n_B) {
208416909a7fSStefano Zampini     if (pcbddc->switch_static) {
20859566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
20869566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
20879566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
20889566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
208916909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
20909566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N));
209116909a7fSStefano Zampini       } else {
20929566063dSJacob Faibussowitsch         PetscCall(MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N));
20939566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(lA,pcis->vec2_N,pcis->vec1_N));
20949566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N));
209516909a7fSStefano Zampini       }
20969566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD));
20979566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD));
209816909a7fSStefano Zampini     } else {
20999566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcis->A_BI,pcis->vec1_B,pcis->vec3_D));
210016909a7fSStefano Zampini     }
210116909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
210216909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
21039566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(lA,pcis->vec1_D,pcis->vec3_D));
210416909a7fSStefano Zampini     } else {
21059566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N));
21069566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N));
21079566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D));
210816909a7fSStefano Zampini     }
2109b097fa66SStefano Zampini   }
21109566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
21119566063dSJacob Faibussowitsch   PetscCall(KSPSolveTranspose(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D));
21129566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
21139566063dSJacob Faibussowitsch   PetscCall(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec4_D));
21148ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
2115b097fa66SStefano Zampini     if (pcbddc->switch_static) {
21169566063dSJacob Faibussowitsch       PetscCall(VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D));
2117b097fa66SStefano Zampini     } else {
21189566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D));
2119b097fa66SStefano Zampini     }
21209566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE));
21219566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE));
2122b097fa66SStefano Zampini   } else {
2123b097fa66SStefano Zampini     if (pcbddc->switch_static) {
21249566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D));
2125b097fa66SStefano Zampini     } else {
21269566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec4_D,m_one));
2127b097fa66SStefano Zampini     }
21289566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE));
21299566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE));
2130b097fa66SStefano Zampini   }
213127b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
21329566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE));
2133537c1cdfSStefano Zampini   }
21341dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2135f913dca9SStefano Zampini     pcbddc->work_change = r;
21369566063dSJacob Faibussowitsch     PetscCall(VecCopy(z,pcbddc->work_change));
21379566063dSJacob Faibussowitsch     PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z));
21381dd7afcfSStefano Zampini   }
213950efa1b5SStefano Zampini   PetscFunctionReturn(0);
214050efa1b5SStefano Zampini }
2141674ae819SStefano Zampini 
21429326c5c6Sstefano_zampini PetscErrorCode PCReset_BDDC(PC pc)
2143da1bb401SStefano Zampini {
2144da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
21459326c5c6Sstefano_zampini   PC_IS          *pcis = (PC_IS*)pc->data;
21469326c5c6Sstefano_zampini   KSP            kspD,kspR,kspC;
2147da1bb401SStefano Zampini 
2148da1bb401SStefano Zampini   PetscFunctionBegin;
2149674ae819SStefano Zampini   /* free BDDC custom data  */
21509566063dSJacob Faibussowitsch   PetscCall(PCBDDCResetCustomization(pc));
2151674ae819SStefano Zampini   /* destroy objects related to topography */
21529566063dSJacob Faibussowitsch   PetscCall(PCBDDCResetTopography(pc));
215334a97f8cSStefano Zampini   /* destroy objects for scaling operator */
21549566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingDestroy(pc));
2155674ae819SStefano Zampini   /* free solvers stuff */
21569566063dSJacob Faibussowitsch   PetscCall(PCBDDCResetSolvers(pc));
215762a6ff1dSStefano Zampini   /* free global vectors needed in presolve */
21589566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->temp_solution));
21599566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->original_rhs));
21601dd7afcfSStefano Zampini   /* free data created by PCIS */
21619566063dSJacob Faibussowitsch   PetscCall(PCISDestroy(pc));
21629326c5c6Sstefano_zampini 
21639326c5c6Sstefano_zampini   /* restore defaults */
21649326c5c6Sstefano_zampini   kspD = pcbddc->ksp_D;
21659326c5c6Sstefano_zampini   kspR = pcbddc->ksp_R;
21669326c5c6Sstefano_zampini   kspC = pcbddc->coarse_ksp;
21679566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(pc->data,sizeof(*pcbddc)));
21689326c5c6Sstefano_zampini   pcis->n_neigh                     = -1;
21699326c5c6Sstefano_zampini   pcis->scaling_factor              = 1.0;
21709326c5c6Sstefano_zampini   pcis->reusesubmatrices            = PETSC_TRUE;
21719326c5c6Sstefano_zampini   pcbddc->use_local_adj             = PETSC_TRUE;
21729326c5c6Sstefano_zampini   pcbddc->use_vertices              = PETSC_TRUE;
21739326c5c6Sstefano_zampini   pcbddc->use_edges                 = PETSC_TRUE;
21749326c5c6Sstefano_zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
21759326c5c6Sstefano_zampini   pcbddc->vertex_size               = 1;
21769326c5c6Sstefano_zampini   pcbddc->recompute_topography      = PETSC_TRUE;
21779326c5c6Sstefano_zampini   pcbddc->coarse_size               = -1;
21789326c5c6Sstefano_zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
21799326c5c6Sstefano_zampini   pcbddc->coarsening_ratio          = 8;
21809326c5c6Sstefano_zampini   pcbddc->coarse_eqs_per_proc       = 1;
21819326c5c6Sstefano_zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
21829326c5c6Sstefano_zampini   pcbddc->nedfield                  = -1;
21839326c5c6Sstefano_zampini   pcbddc->nedglobal                 = PETSC_TRUE;
21849326c5c6Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
21859326c5c6Sstefano_zampini   pcbddc->sub_schurs_layers         = -1;
21869326c5c6Sstefano_zampini   pcbddc->ksp_D                     = kspD;
21879326c5c6Sstefano_zampini   pcbddc->ksp_R                     = kspR;
21889326c5c6Sstefano_zampini   pcbddc->coarse_ksp                = kspC;
21899326c5c6Sstefano_zampini   PetscFunctionReturn(0);
21909326c5c6Sstefano_zampini }
21919326c5c6Sstefano_zampini 
21929326c5c6Sstefano_zampini PetscErrorCode PCDestroy_BDDC(PC pc)
21939326c5c6Sstefano_zampini {
21949326c5c6Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
21959326c5c6Sstefano_zampini 
21969326c5c6Sstefano_zampini   PetscFunctionBegin;
21979566063dSJacob Faibussowitsch   PetscCall(PCReset_BDDC(pc));
21989566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcbddc->ksp_D));
21999566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcbddc->ksp_R));
22009566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcbddc->coarse_ksp));
22019566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",NULL));
22029566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",NULL));
22039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",NULL));
22049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL));
22059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",NULL));
220632fe681dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesLocalIS_C",NULL));
220732fe681dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesIS_C",NULL));
22089566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL));
22099566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL));
22109566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL));
22119566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL));
22129566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL));
22139566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",NULL));
22149566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL));
22159566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",NULL));
22169566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL));
22179566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",NULL));
22189566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL));
22199566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",NULL));
22209566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL));
22219566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",NULL));
22229566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL));
22239566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL));
22249566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL));
22259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL));
22269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",NULL));
22279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",NULL));
22289566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
2229da1bb401SStefano Zampini   PetscFunctionReturn(0);
2230da1bb401SStefano Zampini }
22311e6b0712SBarry Smith 
2232ab8c8b98SStefano Zampini static PetscErrorCode PCSetCoordinates_BDDC(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
2233ab8c8b98SStefano Zampini {
2234ab8c8b98SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2235ab8c8b98SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
2236ab8c8b98SStefano Zampini 
2237ab8c8b98SStefano Zampini   PetscFunctionBegin;
22389566063dSJacob Faibussowitsch   PetscCall(PetscFree(mat_graph->coords));
22399566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nloc*dim,&mat_graph->coords));
22409566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(mat_graph->coords,coords,nloc*dim));
2241ab8c8b98SStefano Zampini   mat_graph->cnloc = nloc;
2242ab8c8b98SStefano Zampini   mat_graph->cdim  = dim;
2243ab8c8b98SStefano Zampini   mat_graph->cloc  = PETSC_FALSE;
22444f819b78SStefano Zampini   /* flg setup */
22454f819b78SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
22464f819b78SStefano Zampini   pcbddc->corner_selected = PETSC_FALSE;
2247ab8c8b98SStefano Zampini   PetscFunctionReturn(0);
2248ab8c8b98SStefano Zampini }
2249ab8c8b98SStefano Zampini 
2250a06fd7f2SStefano Zampini static PetscErrorCode PCPreSolveChangeRHS_BDDC(PC pc, PetscBool* change)
2251a06fd7f2SStefano Zampini {
2252a06fd7f2SStefano Zampini   PetscFunctionBegin;
2253a06fd7f2SStefano Zampini   *change = PETSC_TRUE;
2254a06fd7f2SStefano Zampini   PetscFunctionReturn(0);
2255a06fd7f2SStefano Zampini }
2256a06fd7f2SStefano Zampini 
22573425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
22583425bc38SStefano Zampini {
2259674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
2260266e20e9SStefano Zampini   Vec            work;
22613425bc38SStefano Zampini   PC_IS*         pcis;
22623425bc38SStefano Zampini   PC_BDDC*       pcbddc;
22630c7d97c5SJed Brown 
22643425bc38SStefano Zampini   PetscFunctionBegin;
22659566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat,&mat_ctx));
22663425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
22673425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
22683425bc38SStefano Zampini 
22699566063dSJacob Faibussowitsch   PetscCall(VecSet(fetidp_flux_rhs,0.0));
2270229984c5Sstefano_zampini   /* copy rhs since we may change it during PCPreSolve_BDDC */
2271229984c5Sstefano_zampini   if (!pcbddc->original_rhs) {
22729566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs));
2273229984c5Sstefano_zampini   }
22746cc1294bSstefano_zampini   if (mat_ctx->rhs_flip) {
22759566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(pcbddc->original_rhs,standard_rhs,mat_ctx->rhs_flip));
22766cc1294bSstefano_zampini   } else {
22779566063dSJacob Faibussowitsch     PetscCall(VecCopy(standard_rhs,pcbddc->original_rhs));
22786cc1294bSstefano_zampini   }
2279af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
2280229984c5Sstefano_zampini     /* interface pressure rhs */
22819566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE));
22829566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE));
22839566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD));
22849566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD));
22856cc1294bSstefano_zampini     if (!mat_ctx->rhs_flip) {
22869566063dSJacob Faibussowitsch       PetscCall(VecScale(fetidp_flux_rhs,-1.));
2287229984c5Sstefano_zampini     }
22886cc1294bSstefano_zampini   }
2289c08af4c6SStefano Zampini   /*
2290c08af4c6SStefano Zampini      change of basis for physical rhs if needed
2291c08af4c6SStefano Zampini      It also changes the rhs in case of dirichlet boundaries
2292c08af4c6SStefano Zampini   */
22939566063dSJacob Faibussowitsch   PetscCall(PCPreSolve_BDDC(mat_ctx->pc,NULL,pcbddc->original_rhs,NULL));
2294fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
22959566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcbddc->original_rhs,pcbddc->work_change));
22963738a8e6SStefano Zampini     work = pcbddc->work_change;
2297fc17d649SStefano Zampini    } else {
22983738a8e6SStefano Zampini     work = pcbddc->original_rhs;
2299fc17d649SStefano Zampini   }
23003425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
23019566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD));
23029566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD));
2303fb223d50SStefano Zampini   /* scale rhs since it should be unassembled */
2304fb223d50SStefano Zampini   /* TODO use counter scaling? (also below) */
23059566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD));
23069566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD));
2307674ae819SStefano Zampini   /* Apply partition of unity */
23089566063dSJacob Faibussowitsch   PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B));
23099566063dSJacob Faibussowitsch   /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */
23108eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
23113425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
23129566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0));
23139566063dSJacob Faibussowitsch     PetscCall(KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D));
23149566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0));
2315c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
23169566063dSJacob Faibussowitsch     PetscCall(MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B));
23179566063dSJacob Faibussowitsch     PetscCall(VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B));
23189566063dSJacob Faibussowitsch     PetscCall(VecSet(work,0.0));
23199566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE));
23209566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE));
23219566063dSJacob Faibussowitsch     /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */
23229566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD));
23239566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD));
23249566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B));
23253425bc38SStefano Zampini   }
23263425bc38SStefano Zampini   /* BDDC rhs */
23279566063dSJacob Faibussowitsch   PetscCall(VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B));
23281baa6e33SBarry Smith   if (pcbddc->switch_static) PetscCall(VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D));
23293425bc38SStefano Zampini   /* apply BDDC */
23309566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n));
23319566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE));
23329566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n));
2333229984c5Sstefano_zampini 
23343425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
23359566063dSJacob Faibussowitsch   PetscCall(MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local));
23369566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD));
23379566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD));
2338229984c5Sstefano_zampini   /* Add contribution to interface pressures */
2339229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
23409566063dSJacob Faibussowitsch     PetscCall(MatMult(mat_ctx->B_BB,pcis->vec1_B,mat_ctx->vP));
23411baa6e33SBarry Smith     if (pcbddc->switch_static) PetscCall(MatMultAdd(mat_ctx->B_BI,pcis->vec1_D,mat_ctx->vP,mat_ctx->vP));
23429566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD));
23439566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD));
2344229984c5Sstefano_zampini   }
23453425bc38SStefano Zampini   PetscFunctionReturn(0);
23463425bc38SStefano Zampini }
23471e6b0712SBarry Smith 
23483425bc38SStefano Zampini /*@
23490f202f7eSStefano Zampini  PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side
23503425bc38SStefano Zampini 
23513425bc38SStefano Zampini    Collective
23523425bc38SStefano Zampini 
23533425bc38SStefano Zampini    Input Parameters:
23540f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix object obtained by a call to PCBDDCCreateFETIDPOperators
23550f202f7eSStefano Zampini -  standard_rhs    - the right-hand side of the original linear system
23563425bc38SStefano Zampini 
23573425bc38SStefano Zampini    Output Parameters:
23580f202f7eSStefano Zampini .  fetidp_flux_rhs - the right-hand side for the FETI-DP linear system
23593425bc38SStefano Zampini 
23603425bc38SStefano Zampini    Level: developer
23613425bc38SStefano Zampini 
23623425bc38SStefano Zampini    Notes:
23633425bc38SStefano Zampini 
236416b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCCreateFETIDPOperators()`, `PCBDDCMatFETIDPGetSolution()`
23653425bc38SStefano Zampini @*/
23663425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
23673425bc38SStefano Zampini {
2368674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
23693425bc38SStefano Zampini 
23703425bc38SStefano Zampini   PetscFunctionBegin;
2371266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1);
2372266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_rhs,VEC_CLASSID,2);
2373266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_rhs,VEC_CLASSID,3);
23749566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat,&mat_ctx));
2375cac4c232SBarry Smith   PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));
23763425bc38SStefano Zampini   PetscFunctionReturn(0);
23773425bc38SStefano Zampini }
23781e6b0712SBarry Smith 
23793425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
23803425bc38SStefano Zampini {
2381674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
23823425bc38SStefano Zampini   PC_IS*         pcis;
23833425bc38SStefano Zampini   PC_BDDC*       pcbddc;
2384229984c5Sstefano_zampini   Vec            work;
23853425bc38SStefano Zampini 
23863425bc38SStefano Zampini   PetscFunctionBegin;
23879566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat,&mat_ctx));
23883425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
23893425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
23903425bc38SStefano Zampini 
23913425bc38SStefano Zampini   /* apply B_delta^T */
23929566063dSJacob Faibussowitsch   PetscCall(VecSet(pcis->vec1_B,0.));
23939566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE));
23949566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE));
23959566063dSJacob Faibussowitsch   PetscCall(MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B));
2396229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
23979566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE));
23989566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE));
23999566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(mat_ctx->Bt_BB,mat_ctx->vP,pcis->vec1_B,pcis->vec1_B));
2400229984c5Sstefano_zampini   }
2401229984c5Sstefano_zampini 
24023425bc38SStefano Zampini   /* compute rhs for BDDC application */
24039566063dSJacob Faibussowitsch   PetscCall(VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B));
24048eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
24059566063dSJacob Faibussowitsch     PetscCall(VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D));
2406229984c5Sstefano_zampini     if (mat_ctx->l2g_p) {
24079566063dSJacob Faibussowitsch       PetscCall(VecScale(mat_ctx->vP,-1.));
24089566063dSJacob Faibussowitsch       PetscCall(MatMultAdd(mat_ctx->Bt_BI,mat_ctx->vP,pcis->vec1_D,pcis->vec1_D));
24093425bc38SStefano Zampini     }
2410229984c5Sstefano_zampini   }
2411229984c5Sstefano_zampini 
24123425bc38SStefano Zampini   /* apply BDDC */
24139566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n));
24149566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE));
2415229984c5Sstefano_zampini 
2416229984c5Sstefano_zampini   /* put values into global vector */
2417af140850Sstefano_zampini   if (pcbddc->ChangeOfBasisMatrix) work = pcbddc->work_change;
2418af140850Sstefano_zampini   else work = standard_sol;
24199566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE));
24209566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE));
24218eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
24223425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
24239566063dSJacob Faibussowitsch     PetscCall(MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D));
24249566063dSJacob Faibussowitsch     PetscCall(VecAYPX(pcis->vec1_D,-1.0,mat_ctx->temp_solution_D));
24259566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0));
24269566063dSJacob Faibussowitsch     PetscCall(KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec1_D));
24279566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0));
2428c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
24293425bc38SStefano Zampini   }
2430229984c5Sstefano_zampini 
24319566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE));
24329566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE));
2433266e20e9SStefano Zampini   /* add p0 solution to final solution */
24349566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignGetOrSetP0(mat_ctx->pc,work,PETSC_FALSE));
24351baa6e33SBarry Smith   if (pcbddc->ChangeOfBasisMatrix) PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix,work,standard_sol));
24369566063dSJacob Faibussowitsch   PetscCall(PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol));
2437af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
24389566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE));
24399566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE));
2440229984c5Sstefano_zampini   }
24413425bc38SStefano Zampini   PetscFunctionReturn(0);
24423425bc38SStefano Zampini }
24431e6b0712SBarry Smith 
24445a1e936bSStefano Zampini static PetscErrorCode PCView_BDDCIPC(PC pc, PetscViewer viewer)
24455a1e936bSStefano Zampini {
24465a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
24475a1e936bSStefano Zampini   PetscBool      isascii;
24485a1e936bSStefano Zampini 
24495a1e936bSStefano Zampini   PetscFunctionBegin;
24509566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc,&bddcipc_ctx));
24519566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
24525a1e936bSStefano Zampini   if (isascii) {
24539566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"BDDC interface preconditioner\n"));
24545a1e936bSStefano Zampini   }
24559566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushTab(viewer));
24569566063dSJacob Faibussowitsch   PetscCall(PCView(bddcipc_ctx->bddc,viewer));
24579566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopTab(viewer));
24585a1e936bSStefano Zampini   PetscFunctionReturn(0);
24595a1e936bSStefano Zampini }
24605a1e936bSStefano Zampini 
24615a1e936bSStefano Zampini static PetscErrorCode PCSetUp_BDDCIPC(PC pc)
24625a1e936bSStefano Zampini {
24635a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
24645a1e936bSStefano Zampini   PetscBool      isbddc;
24655a1e936bSStefano Zampini   Vec            vv;
24665a1e936bSStefano Zampini   IS             is;
24675a1e936bSStefano Zampini   PC_IS          *pcis;
24685a1e936bSStefano Zampini 
24695a1e936bSStefano Zampini   PetscFunctionBegin;
24709566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc,&bddcipc_ctx));
24719566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)bddcipc_ctx->bddc,PCBDDC,&isbddc));
247228b400f6SJacob Faibussowitsch   PetscCheck(isbddc,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid type %s. Must be of type bddc",((PetscObject)bddcipc_ctx->bddc)->type_name);
24739566063dSJacob Faibussowitsch   PetscCall(PCSetUp(bddcipc_ctx->bddc));
24745a1e936bSStefano Zampini 
24755a1e936bSStefano Zampini   /* create interface scatter */
24765a1e936bSStefano Zampini   pcis = (PC_IS*)(bddcipc_ctx->bddc->data);
24779566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l));
24789566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(pc->pmat,&vv,NULL));
24799566063dSJacob Faibussowitsch   PetscCall(ISRenumber(pcis->is_B_global,NULL,NULL,&is));
24809566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(vv,is,pcis->vec1_B,NULL,&bddcipc_ctx->g2l));
24819566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
24829566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&vv));
24835a1e936bSStefano Zampini   PetscFunctionReturn(0);
24845a1e936bSStefano Zampini }
24855a1e936bSStefano Zampini 
24865a1e936bSStefano Zampini static PetscErrorCode PCApply_BDDCIPC(PC pc, Vec r, Vec x)
24875a1e936bSStefano Zampini {
24885a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
24895a1e936bSStefano Zampini   PC_IS          *pcis;
24905a1e936bSStefano Zampini   VecScatter     tmps;
24915a1e936bSStefano Zampini 
24925a1e936bSStefano Zampini   PetscFunctionBegin;
24939566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc,&bddcipc_ctx));
24945a1e936bSStefano Zampini   pcis = (PC_IS*)(bddcipc_ctx->bddc->data);
24955a1e936bSStefano Zampini   tmps = pcis->global_to_B;
24965a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
24979566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc,r,pcis->vec1_B));
24989566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc,PETSC_FALSE));
24999566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc,pcis->vec1_B,x));
25005a1e936bSStefano Zampini   pcis->global_to_B = tmps;
25015a1e936bSStefano Zampini   PetscFunctionReturn(0);
25025a1e936bSStefano Zampini }
25035a1e936bSStefano Zampini 
25045a1e936bSStefano Zampini static PetscErrorCode PCApplyTranspose_BDDCIPC(PC pc, Vec r, Vec x)
25055a1e936bSStefano Zampini {
25065a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25075a1e936bSStefano Zampini   PC_IS          *pcis;
25085a1e936bSStefano Zampini   VecScatter     tmps;
25095a1e936bSStefano Zampini 
25105a1e936bSStefano Zampini   PetscFunctionBegin;
25119566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc,&bddcipc_ctx));
25125a1e936bSStefano Zampini   pcis = (PC_IS*)(bddcipc_ctx->bddc->data);
25135a1e936bSStefano Zampini   tmps = pcis->global_to_B;
25145a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
25159566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc,r,pcis->vec1_B));
25169566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc,PETSC_TRUE));
25179566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc,pcis->vec1_B,x));
25185a1e936bSStefano Zampini   pcis->global_to_B = tmps;
25195a1e936bSStefano Zampini   PetscFunctionReturn(0);
25205a1e936bSStefano Zampini }
25215a1e936bSStefano Zampini 
25225a1e936bSStefano Zampini static PetscErrorCode PCDestroy_BDDCIPC(PC pc)
25235a1e936bSStefano Zampini {
25245a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25255a1e936bSStefano Zampini 
25265a1e936bSStefano Zampini   PetscFunctionBegin;
25279566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc,&bddcipc_ctx));
25289566063dSJacob Faibussowitsch   PetscCall(PCDestroy(&bddcipc_ctx->bddc));
25299566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l));
25309566063dSJacob Faibussowitsch   PetscCall(PetscFree(bddcipc_ctx));
25315a1e936bSStefano Zampini   PetscFunctionReturn(0);
25325a1e936bSStefano Zampini }
25335a1e936bSStefano Zampini 
25343425bc38SStefano Zampini /*@
25350f202f7eSStefano Zampini  PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system
25363425bc38SStefano Zampini 
25373425bc38SStefano Zampini    Collective
25383425bc38SStefano Zampini 
25393425bc38SStefano Zampini    Input Parameters:
25400f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators
25410f202f7eSStefano Zampini -  fetidp_flux_sol - the solution of the FETI-DP linear system
25423425bc38SStefano Zampini 
25433425bc38SStefano Zampini    Output Parameters:
25440f202f7eSStefano Zampini .  standard_sol    - the solution defined on the physical domain
25453425bc38SStefano Zampini 
25463425bc38SStefano Zampini    Level: developer
25473425bc38SStefano Zampini 
25483425bc38SStefano Zampini    Notes:
25493425bc38SStefano Zampini 
255016b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCCreateFETIDPOperators()`, `PCBDDCMatFETIDPGetRHS()`
25513425bc38SStefano Zampini @*/
25523425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
25533425bc38SStefano Zampini {
2554674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
25553425bc38SStefano Zampini 
25563425bc38SStefano Zampini   PetscFunctionBegin;
2557266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1);
2558266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_sol,VEC_CLASSID,2);
2559266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_sol,VEC_CLASSID,3);
25609566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat,&mat_ctx));
2561cac4c232SBarry Smith   PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));
25623425bc38SStefano Zampini   PetscFunctionReturn(0);
25633425bc38SStefano Zampini }
25641e6b0712SBarry Smith 
2565547c9a8eSstefano_zampini static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, PetscBool fully_redundant, const char* prefix, Mat *fetidp_mat, PC *fetidp_pc)
25663425bc38SStefano Zampini {
2567674ae819SStefano Zampini 
2568674ae819SStefano Zampini   FETIDPMat_ctx  fetidpmat_ctx;
25693425bc38SStefano Zampini   Mat            newmat;
2570674ae819SStefano Zampini   FETIDPPC_ctx   fetidppc_ctx;
25713425bc38SStefano Zampini   PC             newpc;
2572ce94432eSBarry Smith   MPI_Comm       comm;
25733425bc38SStefano Zampini 
25743425bc38SStefano Zampini   PetscFunctionBegin;
25759566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)pc,&comm));
257615579a77SStefano Zampini   /* FETI-DP matrix */
25779566063dSJacob Faibussowitsch   PetscCall(PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx));
25781720468bSStefano Zampini   fetidpmat_ctx->fully_redundant = fully_redundant;
25799566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetupFETIDPMatContext(fetidpmat_ctx));
25809566063dSJacob Faibussowitsch   PetscCall(MatCreateShell(comm,fetidpmat_ctx->n,fetidpmat_ctx->n,fetidpmat_ctx->N,fetidpmat_ctx->N,fetidpmat_ctx,&newmat));
25819566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)newmat,!fetidpmat_ctx->l2g_lambda_only ? "F" : "G"));
25829566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult));
25839566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(newmat,MATOP_MULT_TRANSPOSE,(void (*)(void))FETIDPMatMultTranspose));
25849566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat));
258515579a77SStefano Zampini   /* propagate MatOptions */
258615579a77SStefano Zampini   {
258715579a77SStefano Zampini     PC_BDDC   *pcbddc = (PC_BDDC*)fetidpmat_ctx->pc->data;
2588*b94d7dedSBarry Smith     PetscBool isset,issym;
258915579a77SStefano Zampini 
2590*b94d7dedSBarry Smith     PetscCall(MatIsSymmetricKnown(pc->mat,&isset,&issym));
2591*b94d7dedSBarry Smith     if ((isset && issym) || pcbddc->symmetric_primal) PetscCall(MatSetOption(newmat,MAT_SYMMETRIC,PETSC_TRUE));
259215579a77SStefano Zampini   }
25939566063dSJacob Faibussowitsch   PetscCall(MatSetOptionsPrefix(newmat,prefix));
25949566063dSJacob Faibussowitsch   PetscCall(MatAppendOptionsPrefix(newmat,"fetidp_"));
25959566063dSJacob Faibussowitsch   PetscCall(MatSetUp(newmat));
259615579a77SStefano Zampini   /* FETI-DP preconditioner */
25979566063dSJacob Faibussowitsch   PetscCall(PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx));
25989566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx));
25999566063dSJacob Faibussowitsch   PetscCall(PCCreate(comm,&newpc));
26009566063dSJacob Faibussowitsch   PetscCall(PCSetOperators(newpc,newmat,newmat));
26019566063dSJacob Faibussowitsch   PetscCall(PCSetOptionsPrefix(newpc,prefix));
26029566063dSJacob Faibussowitsch   PetscCall(PCAppendOptionsPrefix(newpc,"fetidp_"));
26039566063dSJacob Faibussowitsch   PetscCall(PCSetErrorIfFailure(newpc,pc->erroriffailure));
260415579a77SStefano Zampini   if (!fetidpmat_ctx->l2g_lambda_only) { /* standard FETI-DP */
26059566063dSJacob Faibussowitsch     PetscCall(PCSetType(newpc,PCSHELL));
26069566063dSJacob Faibussowitsch     PetscCall(PCShellSetName(newpc,"FETI-DP multipliers"));
26079566063dSJacob Faibussowitsch     PetscCall(PCShellSetContext(newpc,fetidppc_ctx));
26089566063dSJacob Faibussowitsch     PetscCall(PCShellSetApply(newpc,FETIDPPCApply));
26099566063dSJacob Faibussowitsch     PetscCall(PCShellSetApplyTranspose(newpc,FETIDPPCApplyTranspose));
26109566063dSJacob Faibussowitsch     PetscCall(PCShellSetView(newpc,FETIDPPCView));
26119566063dSJacob Faibussowitsch     PetscCall(PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC));
26125a1e936bSStefano Zampini   } else { /* saddle-point FETI-DP */
26135a1e936bSStefano Zampini     Mat       M;
26145a1e936bSStefano Zampini     PetscInt  psize;
26155a1e936bSStefano Zampini     PetscBool fake = PETSC_FALSE, isfieldsplit;
2616e1214c54Sstefano_zampini 
26179566063dSJacob Faibussowitsch     PetscCall(ISViewFromOptions(fetidpmat_ctx->lagrange,NULL,"-lag_view"));
26189566063dSJacob Faibussowitsch     PetscCall(ISViewFromOptions(fetidpmat_ctx->pressure,NULL,"-press_view"));
26199566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_PPmat",(PetscObject*)&M));
26209566063dSJacob Faibussowitsch     PetscCall(PCSetType(newpc,PCFIELDSPLIT));
26219566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetIS(newpc,"lag",fetidpmat_ctx->lagrange));
26229566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetIS(newpc,"p",fetidpmat_ctx->pressure));
26239566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetType(newpc,PC_COMPOSITE_SCHUR));
26249566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetSchurFactType(newpc,PC_FIELDSPLIT_SCHUR_FACT_DIAG));
26259566063dSJacob Faibussowitsch     PetscCall(ISGetSize(fetidpmat_ctx->pressure,&psize));
26265a1e936bSStefano Zampini     if (psize != M->rmap->N) {
26275a1e936bSStefano Zampini       Mat      M2;
26285a1e936bSStefano Zampini       PetscInt lpsize;
26295a1e936bSStefano Zampini 
26305a1e936bSStefano Zampini       fake = PETSC_TRUE;
26319566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(fetidpmat_ctx->pressure,&lpsize));
26329566063dSJacob Faibussowitsch       PetscCall(MatCreate(comm,&M2));
26339566063dSJacob Faibussowitsch       PetscCall(MatSetType(M2,MATAIJ));
26349566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(M2,lpsize,lpsize,psize,psize));
26359566063dSJacob Faibussowitsch       PetscCall(MatSetUp(M2));
26369566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(M2,MAT_FINAL_ASSEMBLY));
26379566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(M2,MAT_FINAL_ASSEMBLY));
26389566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSetSchurPre(newpc,PC_FIELDSPLIT_SCHUR_PRE_USER,M2));
26399566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&M2));
26405a1e936bSStefano Zampini     } else {
26419566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSetSchurPre(newpc,PC_FIELDSPLIT_SCHUR_PRE_USER,M));
26425a1e936bSStefano Zampini     }
26439566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetSchurScale(newpc,1.0));
264415579a77SStefano Zampini 
264515579a77SStefano Zampini     /* we need to setfromoptions and setup here to access the blocks */
26469566063dSJacob Faibussowitsch     PetscCall(PCSetFromOptions(newpc));
26479566063dSJacob Faibussowitsch     PetscCall(PCSetUp(newpc));
2648e1214c54Sstefano_zampini 
26495a1e936bSStefano Zampini     /* user may have changed the type (e.g. -fetidp_pc_type none) */
26509566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)newpc,PCFIELDSPLIT,&isfieldsplit));
26515a1e936bSStefano Zampini     if (isfieldsplit) {
26525a1e936bSStefano Zampini       KSP       *ksps;
26535a1e936bSStefano Zampini       PC        ppc,lagpc;
26545a1e936bSStefano Zampini       PetscInt  nn;
2655064a4176SStefano Zampini       PetscBool ismatis,matisok = PETSC_FALSE,check = PETSC_FALSE;
26565a1e936bSStefano Zampini 
2657e1214c54Sstefano_zampini       /* set the solver for the (0,0) block */
26589566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSchurGetSubKSP(newpc,&nn,&ksps));
26595a1e936bSStefano Zampini       if (!nn) { /* not of type PC_COMPOSITE_SCHUR */
26609566063dSJacob Faibussowitsch         PetscCall(PCFieldSplitGetSubKSP(newpc,&nn,&ksps));
26615a1e936bSStefano Zampini         if (!fake) { /* pass pmat to the pressure solver */
26625a1e936bSStefano Zampini           Mat F;
26635a1e936bSStefano Zampini 
26649566063dSJacob Faibussowitsch           PetscCall(KSPGetOperators(ksps[1],&F,NULL));
26659566063dSJacob Faibussowitsch           PetscCall(KSPSetOperators(ksps[1],F,M));
26665a1e936bSStefano Zampini         }
26675a1e936bSStefano Zampini       } else {
2668*b94d7dedSBarry Smith         PetscBool issym,isset;
26695a1e936bSStefano Zampini         Mat       S;
26705a1e936bSStefano Zampini 
26719566063dSJacob Faibussowitsch         PetscCall(PCFieldSplitSchurGetS(newpc,&S));
2672*b94d7dedSBarry Smith         PetscCall(MatIsSymmetricKnown(newmat,&isset,&issym));
2673*b94d7dedSBarry Smith         if (isset) PetscCall(MatSetOption(S,MAT_SYMMETRIC,issym));
26745a1e936bSStefano Zampini       }
26759566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksps[0],&lagpc));
26769566063dSJacob Faibussowitsch       PetscCall(PCSetType(lagpc,PCSHELL));
26779566063dSJacob Faibussowitsch       PetscCall(PCShellSetName(lagpc,"FETI-DP multipliers"));
26789566063dSJacob Faibussowitsch       PetscCall(PCShellSetContext(lagpc,fetidppc_ctx));
26799566063dSJacob Faibussowitsch       PetscCall(PCShellSetApply(lagpc,FETIDPPCApply));
26809566063dSJacob Faibussowitsch       PetscCall(PCShellSetApplyTranspose(lagpc,FETIDPPCApplyTranspose));
26819566063dSJacob Faibussowitsch       PetscCall(PCShellSetView(lagpc,FETIDPPCView));
26829566063dSJacob Faibussowitsch       PetscCall(PCShellSetDestroy(lagpc,PCBDDCDestroyFETIDPPC));
26835a1e936bSStefano Zampini 
26845a1e936bSStefano Zampini       /* Olof's idea: interface Schur complement preconditioner for the mass matrix */
26859566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksps[1],&ppc));
26865a1e936bSStefano Zampini       if (fake) {
26875a1e936bSStefano Zampini         BDDCIPC_ctx    bddcipc_ctx;
2688ff11fd76SStefano Zampini         PetscContainer c;
26895a1e936bSStefano Zampini 
26905a1e936bSStefano Zampini         matisok = PETSC_TRUE;
26915a1e936bSStefano Zampini 
26925a1e936bSStefano Zampini         /* create inner BDDC solver */
26939566063dSJacob Faibussowitsch         PetscCall(PetscNew(&bddcipc_ctx));
26949566063dSJacob Faibussowitsch         PetscCall(PCCreate(comm,&bddcipc_ctx->bddc));
26959566063dSJacob Faibussowitsch         PetscCall(PCSetType(bddcipc_ctx->bddc,PCBDDC));
26969566063dSJacob Faibussowitsch         PetscCall(PCSetOperators(bddcipc_ctx->bddc,M,M));
26979566063dSJacob Faibussowitsch         PetscCall(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_pCSR",(PetscObject*)&c));
26989566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)M,MATIS,&ismatis));
2699ff11fd76SStefano Zampini         if (c && ismatis) {
2700ff11fd76SStefano Zampini           Mat      lM;
2701ff11fd76SStefano Zampini           PetscInt *csr,n;
2702ff11fd76SStefano Zampini 
27039566063dSJacob Faibussowitsch           PetscCall(MatISGetLocalMat(M,&lM));
27049566063dSJacob Faibussowitsch           PetscCall(MatGetSize(lM,&n,NULL));
27059566063dSJacob Faibussowitsch           PetscCall(PetscContainerGetPointer(c,(void**)&csr));
27069566063dSJacob Faibussowitsch           PetscCall(PCBDDCSetLocalAdjacencyGraph(bddcipc_ctx->bddc,n,csr,csr + (n + 1),PETSC_COPY_VALUES));
27079566063dSJacob Faibussowitsch           PetscCall(MatISRestoreLocalMat(M,&lM));
2708ff11fd76SStefano Zampini         }
27099566063dSJacob Faibussowitsch         PetscCall(PCSetOptionsPrefix(bddcipc_ctx->bddc,((PetscObject)ksps[1])->prefix));
27109566063dSJacob Faibussowitsch         PetscCall(PCSetErrorIfFailure(bddcipc_ctx->bddc,pc->erroriffailure));
27119566063dSJacob Faibussowitsch         PetscCall(PCSetFromOptions(bddcipc_ctx->bddc));
27125a1e936bSStefano Zampini 
27135a1e936bSStefano Zampini         /* wrap the interface application */
27149566063dSJacob Faibussowitsch         PetscCall(PCSetType(ppc,PCSHELL));
27159566063dSJacob Faibussowitsch         PetscCall(PCShellSetName(ppc,"FETI-DP pressure"));
27169566063dSJacob Faibussowitsch         PetscCall(PCShellSetContext(ppc,bddcipc_ctx));
27179566063dSJacob Faibussowitsch         PetscCall(PCShellSetSetUp(ppc,PCSetUp_BDDCIPC));
27189566063dSJacob Faibussowitsch         PetscCall(PCShellSetApply(ppc,PCApply_BDDCIPC));
27199566063dSJacob Faibussowitsch         PetscCall(PCShellSetApplyTranspose(ppc,PCApplyTranspose_BDDCIPC));
27209566063dSJacob Faibussowitsch         PetscCall(PCShellSetView(ppc,PCView_BDDCIPC));
27219566063dSJacob Faibussowitsch         PetscCall(PCShellSetDestroy(ppc,PCDestroy_BDDCIPC));
27225a1e936bSStefano Zampini       }
27235a1e936bSStefano Zampini 
27245a1e936bSStefano Zampini       /* determine if we need to assemble M to construct a preconditioner */
27255a1e936bSStefano Zampini       if (!matisok) {
27269566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)M,MATIS,&ismatis));
27279566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompareAny((PetscObject)ppc,&matisok,PCBDDC,PCJACOBI,PCNONE,PCMG,""));
27285a1e936bSStefano Zampini         if (ismatis && !matisok) {
27299566063dSJacob Faibussowitsch           PetscCall(MatConvert(M,MATAIJ,MAT_INPLACE_MATRIX,&M));
27305a1e936bSStefano Zampini         }
27315a1e936bSStefano Zampini       }
2732064a4176SStefano Zampini 
2733064a4176SStefano Zampini       /* run the subproblems to check convergence */
27349566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetBool(NULL,((PetscObject)newmat)->prefix,"-check_saddlepoint",&check,NULL));
2735064a4176SStefano Zampini       if (check) {
2736064a4176SStefano Zampini         PetscInt i;
2737064a4176SStefano Zampini 
2738064a4176SStefano Zampini         for (i=0;i<nn;i++) {
2739064a4176SStefano Zampini           KSP       kspC;
2740064a4176SStefano Zampini           PC        pc;
2741064a4176SStefano Zampini           Mat       F,pF;
2742064a4176SStefano Zampini           Vec       x,y;
2743064a4176SStefano Zampini           PetscBool isschur,prec = PETSC_TRUE;
2744064a4176SStefano Zampini 
27459566063dSJacob Faibussowitsch           PetscCall(KSPCreate(PetscObjectComm((PetscObject)ksps[i]),&kspC));
27469566063dSJacob Faibussowitsch           PetscCall(KSPSetOptionsPrefix(kspC,((PetscObject)ksps[i])->prefix));
27479566063dSJacob Faibussowitsch           PetscCall(KSPAppendOptionsPrefix(kspC,"check_"));
27489566063dSJacob Faibussowitsch           PetscCall(KSPGetOperators(ksps[i],&F,&pF));
27499566063dSJacob Faibussowitsch           PetscCall(PetscObjectTypeCompare((PetscObject)F,MATSCHURCOMPLEMENT,&isschur));
2750064a4176SStefano Zampini           if (isschur) {
2751064a4176SStefano Zampini             KSP  kspS,kspS2;
2752064a4176SStefano Zampini             Mat  A00,pA00,A10,A01,A11;
2753064a4176SStefano Zampini             char prefix[256];
2754064a4176SStefano Zampini 
27559566063dSJacob Faibussowitsch             PetscCall(MatSchurComplementGetKSP(F,&kspS));
27569566063dSJacob Faibussowitsch             PetscCall(MatSchurComplementGetSubMatrices(F,&A00,&pA00,&A01,&A10,&A11));
27579566063dSJacob Faibussowitsch             PetscCall(MatCreateSchurComplement(A00,pA00,A01,A10,A11,&F));
27589566063dSJacob Faibussowitsch             PetscCall(MatSchurComplementGetKSP(F,&kspS2));
27599566063dSJacob Faibussowitsch             PetscCall(PetscSNPrintf(prefix,sizeof(prefix),"%sschur_",((PetscObject)kspC)->prefix));
27609566063dSJacob Faibussowitsch             PetscCall(KSPSetOptionsPrefix(kspS2,prefix));
27619566063dSJacob Faibussowitsch             PetscCall(KSPGetPC(kspS2,&pc));
27629566063dSJacob Faibussowitsch             PetscCall(PCSetType(pc,PCKSP));
27639566063dSJacob Faibussowitsch             PetscCall(PCKSPSetKSP(pc,kspS));
27649566063dSJacob Faibussowitsch             PetscCall(KSPSetFromOptions(kspS2));
27659566063dSJacob Faibussowitsch             PetscCall(KSPGetPC(kspS2,&pc));
27669566063dSJacob Faibussowitsch             PetscCall(PCSetUseAmat(pc,PETSC_TRUE));
2767064a4176SStefano Zampini           } else {
27689566063dSJacob Faibussowitsch             PetscCall(PetscObjectReference((PetscObject)F));
2769064a4176SStefano Zampini           }
27709566063dSJacob Faibussowitsch           PetscCall(KSPSetFromOptions(kspC));
27719566063dSJacob Faibussowitsch           PetscCall(PetscOptionsGetBool(NULL,((PetscObject)kspC)->prefix,"-preconditioned",&prec,NULL));
2772064a4176SStefano Zampini           if (prec)  {
27739566063dSJacob Faibussowitsch             PetscCall(KSPGetPC(ksps[i],&pc));
27749566063dSJacob Faibussowitsch             PetscCall(KSPSetPC(kspC,pc));
2775064a4176SStefano Zampini           }
27769566063dSJacob Faibussowitsch           PetscCall(KSPSetOperators(kspC,F,pF));
27779566063dSJacob Faibussowitsch           PetscCall(MatCreateVecs(F,&x,&y));
27789566063dSJacob Faibussowitsch           PetscCall(VecSetRandom(x,NULL));
27799566063dSJacob Faibussowitsch           PetscCall(MatMult(F,x,y));
27809566063dSJacob Faibussowitsch           PetscCall(KSPSolve(kspC,y,x));
27819566063dSJacob Faibussowitsch           PetscCall(KSPCheckSolve(kspC,pc,x));
27829566063dSJacob Faibussowitsch           PetscCall(KSPDestroy(&kspC));
27839566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&F));
27849566063dSJacob Faibussowitsch           PetscCall(VecDestroy(&x));
27859566063dSJacob Faibussowitsch           PetscCall(VecDestroy(&y));
2786064a4176SStefano Zampini         }
2787064a4176SStefano Zampini       }
27889566063dSJacob Faibussowitsch       PetscCall(PetscFree(ksps));
2789e1214c54Sstefano_zampini     }
27905a1e936bSStefano Zampini   }
27913425bc38SStefano Zampini   /* return pointers for objects created */
27923425bc38SStefano Zampini   *fetidp_mat = newmat;
27933425bc38SStefano Zampini   *fetidp_pc  = newpc;
27943425bc38SStefano Zampini   PetscFunctionReturn(0);
27953425bc38SStefano Zampini }
27961e6b0712SBarry Smith 
279794ef8ddeSSatish Balay /*@C
27980f202f7eSStefano Zampini  PCBDDCCreateFETIDPOperators - Create FETI-DP operators
27993425bc38SStefano Zampini 
28003425bc38SStefano Zampini    Collective
28013425bc38SStefano Zampini 
28023425bc38SStefano Zampini    Input Parameters:
28031720468bSStefano Zampini +  pc - the BDDC preconditioning context (setup should have been called before)
2804547c9a8eSstefano_zampini .  fully_redundant - true for a fully redundant set of Lagrange multipliers
2805547c9a8eSstefano_zampini -  prefix - optional options database prefix for the objects to be created (can be NULL)
280628509bceSStefano Zampini 
280728509bceSStefano Zampini    Output Parameters:
28080f202f7eSStefano Zampini +  fetidp_mat - shell FETI-DP matrix object
28090f202f7eSStefano Zampini -  fetidp_pc  - shell Dirichlet preconditioner for FETI-DP matrix
281028509bceSStefano Zampini 
28113425bc38SStefano Zampini    Level: developer
28123425bc38SStefano Zampini 
28133425bc38SStefano Zampini    Notes:
28140f202f7eSStefano Zampini      Currently the only operations provided for FETI-DP matrix are MatMult and MatMultTranspose
28153425bc38SStefano Zampini 
281616b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCMatFETIDPGetRHS()`, `PCBDDCMatFETIDPGetSolution()`
28173425bc38SStefano Zampini @*/
2818547c9a8eSstefano_zampini PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc)
28193425bc38SStefano Zampini {
28203425bc38SStefano Zampini   PetscFunctionBegin;
28213425bc38SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
28223425bc38SStefano Zampini   if (pc->setupcalled) {
2823cac4c232SBarry Smith     PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,PetscBool,const char*,Mat*,PC*),(pc,fully_redundant,prefix,fetidp_mat,fetidp_pc));
28246080607fSStefano Zampini   } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"You must call PCSetup_BDDC() first");
28253425bc38SStefano Zampini   PetscFunctionReturn(0);
28263425bc38SStefano Zampini }
28270c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
2828da1bb401SStefano Zampini /*MC
2829da1bb401SStefano Zampini    PCBDDC - Balancing Domain Decomposition by Constraints.
28300c7d97c5SJed Brown 
2831be4a8d98Sprj-    An implementation of the BDDC preconditioner based on the bibliography found below.
283228509bceSStefano Zampini 
283328509bceSStefano Zampini    The matrix to be preconditioned (Pmat) must be of type MATIS.
283428509bceSStefano Zampini 
28350f202f7eSStefano Zampini    Currently works with MATIS matrices with local matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers.
283628509bceSStefano Zampini 
283728509bceSStefano Zampini    It also works with unsymmetric and indefinite problems.
283828509bceSStefano Zampini 
2839b6fdb6dfSStefano Zampini    Unlike 'conventional' interface preconditioners, PCBDDC iterates over all degrees of freedom, not just those on the interface. This allows the use of approximate solvers on the subdomains.
2840b6fdb6dfSStefano Zampini 
2841c7017625SStefano Zampini    Approximate local solvers are automatically adapted (see [1]) if the user has attached a nullspace object to the subdomain matrices, and informed BDDC of using approximate solvers (via the command line).
284228509bceSStefano Zampini 
28430f202f7eSStefano Zampini    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. The latter can be customized by using PCBDDCSetLocalAdjacencyGraph()
284430368db7SStefano Zampini    Additional information on dofs can be provided by using PCBDDCSetDofsSplitting(), PCBDDCSetDirichletBoundaries(), PCBDDCSetNeumannBoundaries(), and PCBDDCSetPrimalVerticesIS() and their local counterparts.
284528509bceSStefano Zampini 
28460f202f7eSStefano Zampini    Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). Non-singular modes are retained via SVD.
284728509bceSStefano Zampini 
28480f202f7eSStefano Zampini    Change of basis is performed similarly to [2] when requested. When more than one constraint is present on a single connected component (i.e. an edge or a face), a robust method based on local QR factorizations is used.
28490f202f7eSStefano Zampini    User defined change of basis can be passed to PCBDDC by using PCBDDCSetChangeOfBasisMat()
285028509bceSStefano Zampini 
28510f202f7eSStefano Zampini    The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using a MatPartitioning object.
285228509bceSStefano Zampini 
2853df4d28bfSStefano Zampini    Adaptive selection of primal constraints [4] is supported for SPD systems with high-contrast in the coefficients if MUMPS or MKL_PARDISO are present. Future versions of the code will also consider using PASTIX.
285428509bceSStefano Zampini 
28550f202f7eSStefano Zampini    An experimental interface to the FETI-DP method is available. FETI-DP operators could be created using PCBDDCCreateFETIDPOperators(). A stand-alone class for the FETI-DP method will be provided in the next releases.
28560f202f7eSStefano Zampini 
2857d314f959SVaclav Hapla    Options Database Keys (some of them, run with -help for a complete list):
28580f202f7eSStefano Zampini 
2859a2b725a8SWilliam Gropp +    -pc_bddc_use_vertices <true> - use or not vertices in primal space
28600f202f7eSStefano Zampini .    -pc_bddc_use_edges <true> - use or not edges in primal space
28610f202f7eSStefano Zampini .    -pc_bddc_use_faces <false> - use or not faces in primal space
28620f202f7eSStefano Zampini .    -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems
28630f202f7eSStefano Zampini .    -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only)
28640f202f7eSStefano Zampini .    -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested
28650f202f7eSStefano Zampini .    -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1])
286628509bceSStefano Zampini .    -pc_bddc_levels <0> - maximum number of levels for multilevel
28670f202f7eSStefano 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)
28685459c157SBarry 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)
28690f202f7eSStefano Zampini .    -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling
287071f2caa7Sprj- .    -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)
2871bd2a564bSStefano 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)
287228509bceSStefano Zampini -    -pc_bddc_check_level <0> - set verbosity level of debugging output
287328509bceSStefano Zampini 
287428509bceSStefano Zampini    Options for Dirichlet, Neumann or coarse solver can be set with
287528509bceSStefano Zampini .vb
287628509bceSStefano Zampini       -pc_bddc_dirichlet_
287728509bceSStefano Zampini       -pc_bddc_neumann_
287828509bceSStefano Zampini       -pc_bddc_coarse_
287928509bceSStefano Zampini .ve
2880f9ff08acSPierre Jolivet    e.g. -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. PCBDDC uses by default KSPPREONLY and PCLU.
288128509bceSStefano Zampini 
28820f202f7eSStefano Zampini    When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified as
288328509bceSStefano Zampini .vb
2884312be037SStefano Zampini       -pc_bddc_dirichlet_lN_
2885312be037SStefano Zampini       -pc_bddc_neumann_lN_
2886312be037SStefano Zampini       -pc_bddc_coarse_lN_
288728509bceSStefano Zampini .ve
28880f202f7eSStefano Zampini    Note that level number ranges from the finest (0) to the coarsest (N).
28890f202f7eSStefano Zampini    In order to specify options for the BDDC operators at the coarser levels (and not for the solvers), prepend -pc_bddc_coarse_ or -pc_bddc_coarse_l to the option, e.g.
28900f202f7eSStefano Zampini .vb
28910f202f7eSStefano Zampini      -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3
28920f202f7eSStefano Zampini .ve
28930f202f7eSStefano 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
2894da1bb401SStefano Zampini 
2895be4a8d98Sprj-    References:
2896606c0280SSatish Balay +  * - C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149--168, March 2007
2897606c0280SSatish Balay .  * - A. Klawonn and O. B. Widlund. "Dual-Primal FETI Methods for Linear Elasticity", Communications on Pure and Applied Mathematics Volume 59, Issue 11, pages 1523--1572, November 2006
2898606c0280SSatish Balay .  * - J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", Computing Volume 83, Issue 2--3, pages 55--85, November 2008
2899606c0280SSatish Balay -  * - C. Pechstein and C. R. Dohrmann. "Modern domain decomposition methods BDDC, deluxe scaling, and an algebraic approach", Seminar talk, Linz, December 2013, http://people.ricam.oeaw.ac.at/c.pechstein/pechstein-bddc2013.pdf
2900be4a8d98Sprj- 
2901da1bb401SStefano Zampini    Level: intermediate
2902da1bb401SStefano Zampini 
2903e94cfbe0SPatrick Sanan    Developer Notes:
2904da1bb401SStefano Zampini 
2905da1bb401SStefano Zampini    Contributed by Stefano Zampini
2906da1bb401SStefano Zampini 
2907db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `MATIS`
2908da1bb401SStefano Zampini M*/
2909b2573a8aSBarry Smith 
29108cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
2911da1bb401SStefano Zampini {
2912da1bb401SStefano Zampini   PC_BDDC             *pcbddc;
2913da1bb401SStefano Zampini 
2914da1bb401SStefano Zampini   PetscFunctionBegin;
29159566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(pc,&pcbddc));
29163ec1f749SStefano Zampini   pc->data = pcbddc;
2917da1bb401SStefano Zampini 
2918da1bb401SStefano Zampini   /* create PCIS data structure */
29199566063dSJacob Faibussowitsch   PetscCall(PCISCreate(pc));
2920da1bb401SStefano Zampini 
29219326c5c6Sstefano_zampini   /* create local graph structure */
29229566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphCreate(&pcbddc->mat_graph));
29239326c5c6Sstefano_zampini 
29249326c5c6Sstefano_zampini   /* BDDC nonzero defaults */
29256d9e27e4SStefano Zampini   pcbddc->use_nnsp                  = PETSC_TRUE;
292608a5cf49SStefano Zampini   pcbddc->use_local_adj             = PETSC_TRUE;
292747d04d0dSStefano Zampini   pcbddc->use_vertices              = PETSC_TRUE;
292847d04d0dSStefano Zampini   pcbddc->use_edges                 = PETSC_TRUE;
29293301b35fSStefano Zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
293014f95afaSStefano Zampini   pcbddc->vertex_size               = 1;
2931c703fcc7SStefano Zampini   pcbddc->recompute_topography      = PETSC_TRUE;
293268457ee5SStefano Zampini   pcbddc->coarse_size               = -1;
293385c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
293447d04d0dSStefano Zampini   pcbddc->coarsening_ratio          = 8;
293557de7509SStefano Zampini   pcbddc->coarse_eqs_per_proc       = 1;
293627b6a85dSStefano Zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
29371e0482f5SStefano Zampini   pcbddc->nedfield                  = -1;
29381e0482f5SStefano Zampini   pcbddc->nedglobal                 = PETSC_TRUE;
2939be12c134Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
2940b96c3477SStefano Zampini   pcbddc->sub_schurs_layers         = -1;
2941bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[0]     = 0.0;
2942bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[1]     = 0.0;
2943b7eb3628SStefano Zampini 
2944da1bb401SStefano Zampini   /* function pointers */
2945da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
294693bd9ae7SStefano Zampini   pc->ops->applytranspose      = PCApplyTranspose_BDDC;
2947da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
2948da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
2949da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
29506b78500eSPatrick Sanan   pc->ops->view                = PCView_BDDC;
29510a545947SLisandro Dalcin   pc->ops->applyrichardson     = NULL;
29520a545947SLisandro Dalcin   pc->ops->applysymmetricleft  = NULL;
29530a545947SLisandro Dalcin   pc->ops->applysymmetricright = NULL;
2954534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
2955534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
29569326c5c6Sstefano_zampini   pc->ops->reset               = PCReset_BDDC;
2957da1bb401SStefano Zampini 
2958da1bb401SStefano Zampini   /* composing function */
29599566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",PCBDDCSetDiscreteGradient_BDDC));
29609566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",PCBDDCSetDivergenceMat_BDDC));
29619566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",PCBDDCSetChangeOfBasisMat_BDDC));
29629566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC));
29639566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",PCBDDCSetPrimalVerticesIS_BDDC));
29649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesLocalIS_C",PCBDDCGetPrimalVerticesLocalIS_BDDC));
29659566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesIS_C",PCBDDCGetPrimalVerticesIS_BDDC));
29669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC));
29679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC));
29689566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC));
29699566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC));
29709566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC));
29719566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",PCBDDCSetDirichletBoundariesLocal_BDDC));
29729566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC));
29739566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",PCBDDCSetNeumannBoundariesLocal_BDDC));
29749566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC));
29759566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",PCBDDCGetDirichletBoundariesLocal_BDDC));
29769566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC));
29779566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",PCBDDCGetNeumannBoundariesLocal_BDDC));
29789566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC));
29799566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",PCBDDCSetDofsSplittingLocal_BDDC));
29809566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC));
29819566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC));
29829566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC));
29839566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC));
29849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",PCPreSolveChangeRHS_BDDC));
29859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",PCSetCoordinates_BDDC));
2986da1bb401SStefano Zampini   PetscFunctionReturn(0);
2987da1bb401SStefano Zampini }
298843371fb9SStefano Zampini 
298943371fb9SStefano Zampini /*@C
299043371fb9SStefano Zampini  PCBDDCInitializePackage - This function initializes everything in the PCBDDC package. It is called
29918a690491SBarry Smith     from PCInitializePackage().
299243371fb9SStefano Zampini 
299343371fb9SStefano Zampini  Level: developer
299443371fb9SStefano Zampini 
2995db781477SPatrick Sanan  .seealso: `PetscInitialize()`
299643371fb9SStefano Zampini @*/
299743371fb9SStefano Zampini PetscErrorCode PCBDDCInitializePackage(void)
299843371fb9SStefano Zampini {
299943371fb9SStefano Zampini   int            i;
300043371fb9SStefano Zampini 
300143371fb9SStefano Zampini   PetscFunctionBegin;
300243371fb9SStefano Zampini   if (PCBDDCPackageInitialized) PetscFunctionReturn(0);
300343371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_TRUE;
30049566063dSJacob Faibussowitsch   PetscCall(PetscRegisterFinalize(PCBDDCFinalizePackage));
300543371fb9SStefano Zampini 
300643371fb9SStefano Zampini   /* general events */
30079566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCTopo",PC_CLASSID,&PC_BDDC_Topology[0]));
30089566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCLKSP",PC_CLASSID,&PC_BDDC_LocalSolvers[0]));
30099566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCLWor",PC_CLASSID,&PC_BDDC_LocalWork[0]));
30109566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCorr",PC_CLASSID,&PC_BDDC_CorrectionSetUp[0]));
30119566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCASet",PC_CLASSID,&PC_BDDC_ApproxSetUp[0]));
30129566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCAApp",PC_CLASSID,&PC_BDDC_ApproxApply[0]));
30139566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCSet",PC_CLASSID,&PC_BDDC_CoarseSetUp[0]));
30149566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCKSP",PC_CLASSID,&PC_BDDC_CoarseSolver[0]));
30159566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCAdap",PC_CLASSID,&PC_BDDC_AdaptiveSetUp[0]));
30169566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCScal",PC_CLASSID,&PC_BDDC_Scaling[0]));
30179566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCSchr",PC_CLASSID,&PC_BDDC_Schurs[0]));
30189566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCDirS",PC_CLASSID,&PC_BDDC_Solves[0][0]));
30199566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCNeuS",PC_CLASSID,&PC_BDDC_Solves[0][1]));
30209566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCoaS",PC_CLASSID,&PC_BDDC_Solves[0][2]));
302143371fb9SStefano Zampini   for (i=1;i<PETSC_PCBDDC_MAXLEVELS;i++) {
302243371fb9SStefano Zampini     char ename[32];
302343371fb9SStefano Zampini 
30249566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCTopo l%02d",i));
30259566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Topology[i]));
30269566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCLKSP l%02d",i));
30279566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_LocalSolvers[i]));
30289566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCLWor l%02d",i));
30299566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_LocalWork[i]));
30309566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCCorr l%02d",i));
30319566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CorrectionSetUp[i]));
30329566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCASet l%02d",i));
30339566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_ApproxSetUp[i]));
30349566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCAApp l%02d",i));
30359566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_ApproxApply[i]));
30369566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCCSet l%02d",i));
30379566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CoarseSetUp[i]));
30389566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCCKSP l%02d",i));
30399566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CoarseSolver[i]));
30409566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCAdap l%02d",i));
30419566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_AdaptiveSetUp[i]));
30429566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCScal l%02d",i));
30439566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Scaling[i]));
30449566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCSchr l%02d",i));
30459566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Schurs[i]));
30469566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCDirS l%02d",i));
30479566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Solves[i][0]));
30489566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCNeuS l%02d",i));
30499566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Solves[i][1]));
30509566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCCoaS l%02d",i));
30519566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Solves[i][2]));
305243371fb9SStefano Zampini   }
305343371fb9SStefano Zampini   PetscFunctionReturn(0);
305443371fb9SStefano Zampini }
305543371fb9SStefano Zampini 
305643371fb9SStefano Zampini /*@C
305743371fb9SStefano Zampini  PCBDDCFinalizePackage - This function frees everything from the PCBDDC package. It is
305843371fb9SStefano Zampini     called from PetscFinalize() automatically.
305943371fb9SStefano Zampini 
306043371fb9SStefano Zampini  Level: developer
306143371fb9SStefano Zampini 
3062db781477SPatrick Sanan  .seealso: `PetscFinalize()`
306343371fb9SStefano Zampini @*/
306443371fb9SStefano Zampini PetscErrorCode PCBDDCFinalizePackage(void)
306543371fb9SStefano Zampini {
306643371fb9SStefano Zampini   PetscFunctionBegin;
306743371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_FALSE;
306843371fb9SStefano Zampini   PetscFunctionReturn(0);
306943371fb9SStefano Zampini }
3070