xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 5e5bbd0a99ea6ef6b187abb9b4a6405ccdf6db1e)
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 
22*5e5bbd0aSStefano Zampini #include <petsc/private/pcbddcimpl.h> /*I "petscpc.h" I*/  /* includes for fortran wrappers */
23*5e5bbd0aSStefano 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 }
409b9b85e73SStefano Zampini /*@
410906d46d4SStefano Zampini  PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs
411b9b85e73SStefano Zampini 
412b9b85e73SStefano Zampini    Collective on PC
413b9b85e73SStefano Zampini 
414b9b85e73SStefano Zampini    Input Parameters:
415b9b85e73SStefano Zampini +  pc - the preconditioning context
4161dd7afcfSStefano Zampini .  change - the change of basis matrix
4171dd7afcfSStefano Zampini -  interior - whether or not the change of basis modifies interior dofs
418b9b85e73SStefano Zampini 
419b9b85e73SStefano Zampini    Level: intermediate
420b9b85e73SStefano Zampini 
421b9b85e73SStefano Zampini    Notes:
422b9b85e73SStefano Zampini 
423db781477SPatrick Sanan .seealso: `PCBDDC`
424b9b85e73SStefano Zampini @*/
4251dd7afcfSStefano Zampini PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change, PetscBool interior)
426b9b85e73SStefano Zampini {
427b9b85e73SStefano Zampini   PetscFunctionBegin;
428b9b85e73SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
429b9b85e73SStefano Zampini   PetscValidHeaderSpecific(change,MAT_CLASSID,2);
430906d46d4SStefano Zampini   PetscCheckSameComm(pc,1,change,2);
431906d46d4SStefano Zampini   if (pc->mat) {
432906d46d4SStefano Zampini     PetscInt rows_c,cols_c,rows,cols;
4339566063dSJacob Faibussowitsch     PetscCall(MatGetSize(pc->mat,&rows,&cols));
4349566063dSJacob Faibussowitsch     PetscCall(MatGetSize(change,&rows_c,&cols_c));
43563a3b9bcSJacob 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);
43663a3b9bcSJacob 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);
4379566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(pc->mat,&rows,&cols));
4389566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(change,&rows_c,&cols_c));
43963a3b9bcSJacob 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);
44063a3b9bcSJacob 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);
441906d46d4SStefano Zampini   }
442cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetChangeOfBasisMat_C",(PC,Mat,PetscBool),(pc,change,interior));
443b9b85e73SStefano Zampini   PetscFunctionReturn(0);
444b9b85e73SStefano Zampini }
4452d505d7fSStefano Zampini 
44630368db7SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesIS_BDDC(PC pc, IS PrimalVertices)
44730368db7SStefano Zampini {
44830368db7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
44956282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
45030368db7SStefano Zampini 
45130368db7SStefano Zampini   PetscFunctionBegin;
4529566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)PrimalVertices));
45356282151SStefano Zampini   if (pcbddc->user_primal_vertices) {
4549566063dSJacob Faibussowitsch     PetscCall(ISEqual(PrimalVertices,pcbddc->user_primal_vertices,&isequal));
45556282151SStefano Zampini   }
4569566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices));
4579566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local));
45830368db7SStefano Zampini   pcbddc->user_primal_vertices = PrimalVertices;
45956282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
46030368db7SStefano Zampini   PetscFunctionReturn(0);
46130368db7SStefano Zampini }
462ab8c8b98SStefano Zampini 
46330368db7SStefano Zampini /*@
46430368db7SStefano Zampini  PCBDDCSetPrimalVerticesIS - Set additional user defined primal vertices in PCBDDC
46530368db7SStefano Zampini 
46630368db7SStefano Zampini    Collective
46730368db7SStefano Zampini 
46830368db7SStefano Zampini    Input Parameters:
46930368db7SStefano Zampini +  pc - the preconditioning context
47030368db7SStefano Zampini -  PrimalVertices - index set of primal vertices in global numbering (can be empty)
47130368db7SStefano Zampini 
47230368db7SStefano Zampini    Level: intermediate
47330368db7SStefano Zampini 
47430368db7SStefano Zampini    Notes:
47530368db7SStefano Zampini      Any process can list any global node
47630368db7SStefano Zampini 
477db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`, `PCBDDCGetPrimalVerticesLocalIS()`
47830368db7SStefano Zampini @*/
47930368db7SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesIS(PC pc, IS PrimalVertices)
48030368db7SStefano Zampini {
48130368db7SStefano Zampini   PetscFunctionBegin;
48230368db7SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
48330368db7SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
48430368db7SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
485cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetPrimalVerticesIS_C",(PC,IS),(pc,PrimalVertices));
48630368db7SStefano Zampini   PetscFunctionReturn(0);
48730368db7SStefano Zampini }
4882d505d7fSStefano Zampini 
4893100ebe3SStefano Zampini static PetscErrorCode PCBDDCGetPrimalVerticesIS_BDDC(PC pc, IS *is)
4903100ebe3SStefano Zampini {
4913100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC*)pc->data;
4923100ebe3SStefano Zampini 
4933100ebe3SStefano Zampini   PetscFunctionBegin;
4943100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices;
4953100ebe3SStefano Zampini   PetscFunctionReturn(0);
4963100ebe3SStefano Zampini }
4973100ebe3SStefano Zampini 
4983100ebe3SStefano Zampini /*@
4993100ebe3SStefano Zampini  PCBDDCGetPrimalVerticesIS - Get user defined primal vertices set with PCBDDCSetPrimalVerticesIS()
5003100ebe3SStefano Zampini 
5013100ebe3SStefano Zampini    Collective
5023100ebe3SStefano Zampini 
5033100ebe3SStefano Zampini    Input Parameters:
5043100ebe3SStefano Zampini .  pc - the preconditioning context
5053100ebe3SStefano Zampini 
5063100ebe3SStefano Zampini    Output Parameters:
5073100ebe3SStefano Zampini .  is - index set of primal vertices in global numbering (NULL if not set)
5083100ebe3SStefano Zampini 
5093100ebe3SStefano Zampini    Level: intermediate
5103100ebe3SStefano Zampini 
5113100ebe3SStefano Zampini    Notes:
5123100ebe3SStefano Zampini 
513db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`, `PCBDDCGetPrimalVerticesLocalIS()`
5143100ebe3SStefano Zampini @*/
5153100ebe3SStefano Zampini PetscErrorCode PCBDDCGetPrimalVerticesIS(PC pc, IS *is)
5163100ebe3SStefano Zampini {
5173100ebe3SStefano Zampini   PetscFunctionBegin;
5183100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5193100ebe3SStefano Zampini   PetscValidPointer(is,2);
520cac4c232SBarry Smith   PetscUseMethod(pc,"PCBDDCGetPrimalVerticesIS_C",(PC,IS*),(pc,is));
5213100ebe3SStefano Zampini   PetscFunctionReturn(0);
5223100ebe3SStefano Zampini }
5233100ebe3SStefano Zampini 
524674ae819SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
525674ae819SStefano Zampini {
526674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
52756282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
5281e6b0712SBarry Smith 
529674ae819SStefano Zampini   PetscFunctionBegin;
5309566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)PrimalVertices));
53156282151SStefano Zampini   if (pcbddc->user_primal_vertices_local) {
5329566063dSJacob Faibussowitsch     PetscCall(ISEqual(PrimalVertices,pcbddc->user_primal_vertices_local,&isequal));
53356282151SStefano Zampini   }
5349566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices));
5359566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->user_primal_vertices_local));
53630368db7SStefano Zampini   pcbddc->user_primal_vertices_local = PrimalVertices;
53756282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
538674ae819SStefano Zampini   PetscFunctionReturn(0);
539674ae819SStefano Zampini }
5403100ebe3SStefano Zampini 
541674ae819SStefano Zampini /*@
54228509bceSStefano Zampini  PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in PCBDDC
543674ae819SStefano Zampini 
54417eb1463SStefano Zampini    Collective
545674ae819SStefano Zampini 
546674ae819SStefano Zampini    Input Parameters:
547674ae819SStefano Zampini +  pc - the preconditioning context
54817eb1463SStefano Zampini -  PrimalVertices - index set of primal vertices in local numbering (can be empty)
549674ae819SStefano Zampini 
550674ae819SStefano Zampini    Level: intermediate
551674ae819SStefano Zampini 
552674ae819SStefano Zampini    Notes:
553674ae819SStefano Zampini 
554db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesLocalIS()`
555674ae819SStefano Zampini @*/
556674ae819SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
557674ae819SStefano Zampini {
558674ae819SStefano Zampini   PetscFunctionBegin;
559674ae819SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
560674ae819SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
56117eb1463SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
562cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));
563674ae819SStefano Zampini   PetscFunctionReturn(0);
564674ae819SStefano Zampini }
5652d505d7fSStefano Zampini 
5663100ebe3SStefano Zampini static PetscErrorCode PCBDDCGetPrimalVerticesLocalIS_BDDC(PC pc, IS *is)
5673100ebe3SStefano Zampini {
5683100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC*)pc->data;
5693100ebe3SStefano Zampini 
5703100ebe3SStefano Zampini   PetscFunctionBegin;
5713100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices_local;
5723100ebe3SStefano Zampini   PetscFunctionReturn(0);
5733100ebe3SStefano Zampini }
5743100ebe3SStefano Zampini 
5753100ebe3SStefano Zampini /*@
5763100ebe3SStefano Zampini  PCBDDCGetPrimalVerticesLocalIS - Get user defined primal vertices set with PCBDDCSetPrimalVerticesLocalIS()
5773100ebe3SStefano Zampini 
5783100ebe3SStefano Zampini    Collective
5793100ebe3SStefano Zampini 
5803100ebe3SStefano Zampini    Input Parameters:
5813100ebe3SStefano Zampini .  pc - the preconditioning context
5823100ebe3SStefano Zampini 
5833100ebe3SStefano Zampini    Output Parameters:
5843100ebe3SStefano Zampini .  is - index set of primal vertices in local numbering (NULL if not set)
5853100ebe3SStefano Zampini 
5863100ebe3SStefano Zampini    Level: intermediate
5873100ebe3SStefano Zampini 
5883100ebe3SStefano Zampini    Notes:
5893100ebe3SStefano Zampini 
590db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetPrimalVerticesIS()`, `PCBDDCGetPrimalVerticesIS()`, `PCBDDCSetPrimalVerticesLocalIS()`
5913100ebe3SStefano Zampini @*/
5923100ebe3SStefano Zampini PetscErrorCode PCBDDCGetPrimalVerticesLocalIS(PC pc, IS *is)
5933100ebe3SStefano Zampini {
5943100ebe3SStefano Zampini   PetscFunctionBegin;
5953100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5963100ebe3SStefano Zampini   PetscValidPointer(is,2);
597cac4c232SBarry Smith   PetscUseMethod(pc,"PCBDDCGetPrimalVerticesLocalIS_C",(PC,IS*),(pc,is));
5983100ebe3SStefano Zampini   PetscFunctionReturn(0);
5993100ebe3SStefano Zampini }
6003100ebe3SStefano Zampini 
6014fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k)
6024fad6a16SStefano Zampini {
6034fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
6044fad6a16SStefano Zampini 
6054fad6a16SStefano Zampini   PetscFunctionBegin;
6064fad6a16SStefano Zampini   pcbddc->coarsening_ratio = k;
6074fad6a16SStefano Zampini   PetscFunctionReturn(0);
6084fad6a16SStefano Zampini }
6091e6b0712SBarry Smith 
6104fad6a16SStefano Zampini /*@
61128509bceSStefano Zampini  PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel
6124fad6a16SStefano Zampini 
6134fad6a16SStefano Zampini    Logically collective on PC
6144fad6a16SStefano Zampini 
6154fad6a16SStefano Zampini    Input Parameters:
6164fad6a16SStefano Zampini +  pc - the preconditioning context
61728509bceSStefano Zampini -  k - coarsening ratio (H/h at the coarser level)
6184fad6a16SStefano Zampini 
6190f202f7eSStefano Zampini    Options Database Keys:
62067b8a455SSatish Balay .    -pc_bddc_coarsening_ratio <int> - Set coarsening ratio used in multilevel coarsening
6214fad6a16SStefano Zampini 
6224fad6a16SStefano Zampini    Level: intermediate
6234fad6a16SStefano Zampini 
6244fad6a16SStefano Zampini    Notes:
6250f202f7eSStefano Zampini      Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level
6264fad6a16SStefano Zampini 
627db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetLevels()`
6284fad6a16SStefano Zampini @*/
6294fad6a16SStefano Zampini PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k)
6304fad6a16SStefano Zampini {
6314fad6a16SStefano Zampini   PetscFunctionBegin;
6324fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
6332b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,k,2);
634cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));
6354fad6a16SStefano Zampini   PetscFunctionReturn(0);
6364fad6a16SStefano Zampini }
6372b510759SStefano Zampini 
638b8ffe317SStefano Zampini /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */
639b8ffe317SStefano Zampini static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc,PetscBool flg)
640b8ffe317SStefano Zampini {
641b8ffe317SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
642b8ffe317SStefano Zampini 
643b8ffe317SStefano Zampini   PetscFunctionBegin;
64485c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = flg;
645b8ffe317SStefano Zampini   PetscFunctionReturn(0);
646b8ffe317SStefano Zampini }
647b8ffe317SStefano Zampini 
648b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool flg)
6492b510759SStefano Zampini {
6502b510759SStefano Zampini   PetscFunctionBegin;
6512b510759SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
652b8ffe317SStefano Zampini   PetscValidLogicalCollectiveBool(pc,flg,2);
653cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetUseExactDirichlet_C",(PC,PetscBool),(pc,flg));
6542b510759SStefano Zampini   PetscFunctionReturn(0);
6552b510759SStefano Zampini }
6561e6b0712SBarry Smith 
6572b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc,PetscInt level)
6584fad6a16SStefano Zampini {
6594fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
6604fad6a16SStefano Zampini 
6614fad6a16SStefano Zampini   PetscFunctionBegin;
6622b510759SStefano Zampini   pcbddc->current_level = level;
6634fad6a16SStefano Zampini   PetscFunctionReturn(0);
6644fad6a16SStefano Zampini }
6651e6b0712SBarry Smith 
666b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level)
667b8ffe317SStefano Zampini {
668b8ffe317SStefano Zampini   PetscFunctionBegin;
669b8ffe317SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
670b8ffe317SStefano Zampini   PetscValidLogicalCollectiveInt(pc,level,2);
671cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetLevel_C",(PC,PetscInt),(pc,level));
672b8ffe317SStefano Zampini   PetscFunctionReturn(0);
673b8ffe317SStefano Zampini }
674b8ffe317SStefano Zampini 
6752b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc,PetscInt levels)
6762b510759SStefano Zampini {
6772b510759SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
6782b510759SStefano Zampini 
6792b510759SStefano Zampini   PetscFunctionBegin;
6807827d75bSBarry 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);
6812b510759SStefano Zampini   pcbddc->max_levels = levels;
6822b510759SStefano Zampini   PetscFunctionReturn(0);
6832b510759SStefano Zampini }
6842b510759SStefano Zampini 
6854fad6a16SStefano Zampini /*@
68637ebbdf7SStefano Zampini  PCBDDCSetLevels - Sets the maximum number of additional levels allowed for multilevel BDDC
6874fad6a16SStefano Zampini 
6884fad6a16SStefano Zampini    Logically collective on PC
6894fad6a16SStefano Zampini 
6904fad6a16SStefano Zampini    Input Parameters:
6914fad6a16SStefano Zampini +  pc - the preconditioning context
69237ebbdf7SStefano Zampini -  levels - the maximum number of levels
6934fad6a16SStefano Zampini 
6940f202f7eSStefano Zampini    Options Database Keys:
69567b8a455SSatish Balay .    -pc_bddc_levels <int> - Set maximum number of levels for multilevel
6964fad6a16SStefano Zampini 
6974fad6a16SStefano Zampini    Level: intermediate
6984fad6a16SStefano Zampini 
6994fad6a16SStefano Zampini    Notes:
70037ebbdf7SStefano Zampini      The default value is 0, that gives the classical two-levels BDDC
7014fad6a16SStefano Zampini 
702db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetCoarseningRatio()`
7034fad6a16SStefano Zampini @*/
7042b510759SStefano Zampini PetscErrorCode PCBDDCSetLevels(PC pc,PetscInt levels)
7054fad6a16SStefano Zampini {
7064fad6a16SStefano Zampini   PetscFunctionBegin;
7074fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
7082b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,levels,2);
709cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetLevels_C",(PC,PetscInt),(pc,levels));
7104fad6a16SStefano Zampini   PetscFunctionReturn(0);
7114fad6a16SStefano Zampini }
7121e6b0712SBarry Smith 
7133b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
7143b03a366Sstefano_zampini {
7153b03a366Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
71656282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
7173b03a366Sstefano_zampini 
7183b03a366Sstefano_zampini   PetscFunctionBegin;
7199566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)DirichletBoundaries));
72056282151SStefano Zampini   if (pcbddc->DirichletBoundaries) {
7219566063dSJacob Faibussowitsch     PetscCall(ISEqual(DirichletBoundaries,pcbddc->DirichletBoundaries,&isequal));
72256282151SStefano Zampini   }
723a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
7249566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal));
7259566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundaries));
72636e030ebSStefano Zampini   pcbddc->DirichletBoundaries = DirichletBoundaries;
72756282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7283b03a366Sstefano_zampini   PetscFunctionReturn(0);
7293b03a366Sstefano_zampini }
7301e6b0712SBarry Smith 
7313b03a366Sstefano_zampini /*@
73228509bceSStefano Zampini  PCBDDCSetDirichletBoundaries - Set IS defining Dirichlet boundaries for the global problem.
7333b03a366Sstefano_zampini 
734785d1243SStefano Zampini    Collective
7353b03a366Sstefano_zampini 
7363b03a366Sstefano_zampini    Input Parameters:
7373b03a366Sstefano_zampini +  pc - the preconditioning context
738785d1243SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries
7393b03a366Sstefano_zampini 
7403b03a366Sstefano_zampini    Level: intermediate
7413b03a366Sstefano_zampini 
7420f202f7eSStefano Zampini    Notes:
7430f202f7eSStefano Zampini      Provide the information if you used MatZeroRows/Columns routines. Any process can list any global node
7443b03a366Sstefano_zampini 
745db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetDirichletBoundariesLocal()`, `MatZeroRows()`, `MatZeroRowsColumns()`
7463b03a366Sstefano_zampini @*/
7473b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
7483b03a366Sstefano_zampini {
7493b03a366Sstefano_zampini   PetscFunctionBegin;
7503b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
751674ae819SStefano Zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
752785d1243SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
753cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));
7543b03a366Sstefano_zampini   PetscFunctionReturn(0);
7553b03a366Sstefano_zampini }
7561e6b0712SBarry Smith 
75782ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc,IS DirichletBoundaries)
7583b03a366Sstefano_zampini {
7593b03a366Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
76056282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
7613b03a366Sstefano_zampini 
7623b03a366Sstefano_zampini   PetscFunctionBegin;
7639566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)DirichletBoundaries));
76456282151SStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
7659566063dSJacob Faibussowitsch     PetscCall(ISEqual(DirichletBoundaries,pcbddc->DirichletBoundariesLocal,&isequal));
76656282151SStefano Zampini   }
767a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
7689566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundariesLocal));
7699566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->DirichletBoundaries));
770785d1243SStefano Zampini   pcbddc->DirichletBoundariesLocal = DirichletBoundaries;
77156282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7723b03a366Sstefano_zampini   PetscFunctionReturn(0);
7733b03a366Sstefano_zampini }
7743b03a366Sstefano_zampini 
7753b03a366Sstefano_zampini /*@
77682ba6b80SStefano Zampini  PCBDDCSetDirichletBoundariesLocal - Set IS defining Dirichlet boundaries for the global problem in local ordering.
7773b03a366Sstefano_zampini 
778785d1243SStefano Zampini    Collective
7793b03a366Sstefano_zampini 
7803b03a366Sstefano_zampini    Input Parameters:
7813b03a366Sstefano_zampini +  pc - the preconditioning context
78282ba6b80SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries (in local ordering)
7833b03a366Sstefano_zampini 
7843b03a366Sstefano_zampini    Level: intermediate
7853b03a366Sstefano_zampini 
7863b03a366Sstefano_zampini    Notes:
7873b03a366Sstefano_zampini 
788db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetDirichletBoundaries()`, `MatZeroRows()`, `MatZeroRowsColumns()`
7893b03a366Sstefano_zampini @*/
79082ba6b80SStefano Zampini PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc,IS DirichletBoundaries)
7913b03a366Sstefano_zampini {
7923b03a366Sstefano_zampini   PetscFunctionBegin;
7933b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
7943b03a366Sstefano_zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
79582ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
796cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetDirichletBoundariesLocal_C",(PC,IS),(pc,DirichletBoundaries));
7973b03a366Sstefano_zampini   PetscFunctionReturn(0);
7983b03a366Sstefano_zampini }
7993b03a366Sstefano_zampini 
80053cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
8010c7d97c5SJed Brown {
8020c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
80356282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
8040c7d97c5SJed Brown 
8050c7d97c5SJed Brown   PetscFunctionBegin;
8069566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries));
80756282151SStefano Zampini   if (pcbddc->NeumannBoundaries) {
8089566063dSJacob Faibussowitsch     PetscCall(ISEqual(NeumannBoundaries,pcbddc->NeumannBoundaries,&isequal));
80956282151SStefano Zampini   }
810a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
8119566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal));
8129566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundaries));
81336e030ebSStefano Zampini   pcbddc->NeumannBoundaries = NeumannBoundaries;
81456282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
8150c7d97c5SJed Brown   PetscFunctionReturn(0);
8160c7d97c5SJed Brown }
8171e6b0712SBarry Smith 
81857527edcSJed Brown /*@
81928509bceSStefano Zampini  PCBDDCSetNeumannBoundaries - Set IS defining Neumann boundaries for the global problem.
82057527edcSJed Brown 
821785d1243SStefano Zampini    Collective
82257527edcSJed Brown 
82357527edcSJed Brown    Input Parameters:
82457527edcSJed Brown +  pc - the preconditioning context
825785d1243SStefano Zampini -  NeumannBoundaries - parallel IS defining the Neumann boundaries
82657527edcSJed Brown 
82757527edcSJed Brown    Level: intermediate
82857527edcSJed Brown 
8290f202f7eSStefano Zampini    Notes:
8300f202f7eSStefano Zampini      Any process can list any global node
83157527edcSJed Brown 
832db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetNeumannBoundariesLocal()`
83357527edcSJed Brown @*/
83453cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
8350c7d97c5SJed Brown {
8360c7d97c5SJed Brown   PetscFunctionBegin;
8370c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
838674ae819SStefano Zampini   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
839785d1243SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
840cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));
84153cdbc3dSStefano Zampini   PetscFunctionReturn(0);
84253cdbc3dSStefano Zampini }
8431e6b0712SBarry Smith 
84482ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc,IS NeumannBoundaries)
8450c7d97c5SJed Brown {
8460c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
84756282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
8480c7d97c5SJed Brown 
8490c7d97c5SJed Brown   PetscFunctionBegin;
8509566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)NeumannBoundaries));
85156282151SStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
8529566063dSJacob Faibussowitsch     PetscCall(ISEqual(NeumannBoundaries,pcbddc->NeumannBoundariesLocal,&isequal));
85356282151SStefano Zampini   }
854a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
8559566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundariesLocal));
8569566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcbddc->NeumannBoundaries));
857785d1243SStefano Zampini   pcbddc->NeumannBoundariesLocal = NeumannBoundaries;
85856282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
8590c7d97c5SJed Brown   PetscFunctionReturn(0);
8600c7d97c5SJed Brown }
8610c7d97c5SJed Brown 
8620c7d97c5SJed Brown /*@
86382ba6b80SStefano Zampini  PCBDDCSetNeumannBoundariesLocal - Set IS defining Neumann boundaries for the global problem in local ordering.
8640c7d97c5SJed Brown 
865785d1243SStefano Zampini    Collective
8660c7d97c5SJed Brown 
8670c7d97c5SJed Brown    Input Parameters:
8680c7d97c5SJed Brown +  pc - the preconditioning context
86982ba6b80SStefano Zampini -  NeumannBoundaries - parallel IS defining the subdomain part of Neumann boundaries (in local ordering)
8700c7d97c5SJed Brown 
8710c7d97c5SJed Brown    Level: intermediate
8720c7d97c5SJed Brown 
8730c7d97c5SJed Brown    Notes:
8740c7d97c5SJed Brown 
875db781477SPatrick Sanan .seealso: `PCBDDC`, `PCBDDCSetNeumannBoundaries()`
8760c7d97c5SJed Brown @*/
87782ba6b80SStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc,IS NeumannBoundaries)
8780c7d97c5SJed Brown {
8790c7d97c5SJed Brown   PetscFunctionBegin;
8800c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
8810c7d97c5SJed Brown   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
88282ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
883cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetNeumannBoundariesLocal_C",(PC,IS),(pc,NeumannBoundaries));
88453cdbc3dSStefano Zampini   PetscFunctionReturn(0);
88553cdbc3dSStefano Zampini }
88653cdbc3dSStefano Zampini 
887da1bb401SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
888da1bb401SStefano Zampini {
889da1bb401SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
890da1bb401SStefano Zampini 
891da1bb401SStefano Zampini   PetscFunctionBegin;
892da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
893da1bb401SStefano Zampini   PetscFunctionReturn(0);
894da1bb401SStefano Zampini }
8951e6b0712SBarry Smith 
896da1bb401SStefano Zampini /*@
897785d1243SStefano Zampini  PCBDDCGetDirichletBoundaries - Get parallel IS for Dirichlet boundaries
898da1bb401SStefano Zampini 
899785d1243SStefano Zampini    Collective
900785d1243SStefano Zampini 
901785d1243SStefano Zampini    Input Parameters:
902785d1243SStefano Zampini .  pc - the preconditioning context
903785d1243SStefano Zampini 
904785d1243SStefano Zampini    Output Parameters:
905785d1243SStefano Zampini .  DirichletBoundaries - index set defining the Dirichlet boundaries
906785d1243SStefano Zampini 
907785d1243SStefano Zampini    Level: intermediate
908785d1243SStefano Zampini 
9090f202f7eSStefano Zampini    Notes:
9100f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetDirichletBoundaries
911785d1243SStefano Zampini 
912db781477SPatrick Sanan .seealso: `PCBDDC`
913785d1243SStefano Zampini @*/
914785d1243SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
915785d1243SStefano Zampini {
916785d1243SStefano Zampini   PetscFunctionBegin;
917785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
918cac4c232SBarry Smith   PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));
919785d1243SStefano Zampini   PetscFunctionReturn(0);
920785d1243SStefano Zampini }
921785d1243SStefano Zampini 
922785d1243SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc,IS *DirichletBoundaries)
923785d1243SStefano Zampini {
924785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
925785d1243SStefano Zampini 
926785d1243SStefano Zampini   PetscFunctionBegin;
927785d1243SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundariesLocal;
928785d1243SStefano Zampini   PetscFunctionReturn(0);
929785d1243SStefano Zampini }
930785d1243SStefano Zampini 
931da1bb401SStefano Zampini /*@
93282ba6b80SStefano Zampini  PCBDDCGetDirichletBoundariesLocal - Get parallel IS for Dirichlet boundaries (in local ordering)
933da1bb401SStefano Zampini 
934785d1243SStefano Zampini    Collective
935da1bb401SStefano Zampini 
936da1bb401SStefano Zampini    Input Parameters:
93728509bceSStefano Zampini .  pc - the preconditioning context
938da1bb401SStefano Zampini 
939da1bb401SStefano Zampini    Output Parameters:
94028509bceSStefano Zampini .  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
941da1bb401SStefano Zampini 
942da1bb401SStefano Zampini    Level: intermediate
943da1bb401SStefano Zampini 
944da1bb401SStefano Zampini    Notes:
9450f202f7eSStefano 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).
9460f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
947da1bb401SStefano Zampini 
948db781477SPatrick Sanan .seealso: `PCBDDC`
949da1bb401SStefano Zampini @*/
95082ba6b80SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc,IS *DirichletBoundaries)
951da1bb401SStefano Zampini {
952da1bb401SStefano Zampini   PetscFunctionBegin;
953da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
954cac4c232SBarry Smith   PetscUseMethod(pc,"PCBDDCGetDirichletBoundariesLocal_C",(PC,IS*),(pc,DirichletBoundaries));
955da1bb401SStefano Zampini   PetscFunctionReturn(0);
956da1bb401SStefano Zampini }
9571e6b0712SBarry Smith 
95853cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
95953cdbc3dSStefano Zampini {
96053cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
96153cdbc3dSStefano Zampini 
96253cdbc3dSStefano Zampini   PetscFunctionBegin;
96353cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
96453cdbc3dSStefano Zampini   PetscFunctionReturn(0);
96553cdbc3dSStefano Zampini }
9661e6b0712SBarry Smith 
96753cdbc3dSStefano Zampini /*@
968785d1243SStefano Zampini  PCBDDCGetNeumannBoundaries - Get parallel IS for Neumann boundaries
96953cdbc3dSStefano Zampini 
970785d1243SStefano Zampini    Collective
971785d1243SStefano Zampini 
972785d1243SStefano Zampini    Input Parameters:
973785d1243SStefano Zampini .  pc - the preconditioning context
974785d1243SStefano Zampini 
975785d1243SStefano Zampini    Output Parameters:
976785d1243SStefano Zampini .  NeumannBoundaries - index set defining the Neumann boundaries
977785d1243SStefano Zampini 
978785d1243SStefano Zampini    Level: intermediate
979785d1243SStefano Zampini 
9800f202f7eSStefano Zampini    Notes:
9810f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetNeumannBoundaries
982785d1243SStefano Zampini 
983db781477SPatrick Sanan .seealso: `PCBDDC`
984785d1243SStefano Zampini @*/
985785d1243SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
986785d1243SStefano Zampini {
987785d1243SStefano Zampini   PetscFunctionBegin;
988785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
989cac4c232SBarry Smith   PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));
990785d1243SStefano Zampini   PetscFunctionReturn(0);
991785d1243SStefano Zampini }
992785d1243SStefano Zampini 
993785d1243SStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc,IS *NeumannBoundaries)
994785d1243SStefano Zampini {
995785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
996785d1243SStefano Zampini 
997785d1243SStefano Zampini   PetscFunctionBegin;
998785d1243SStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundariesLocal;
999785d1243SStefano Zampini   PetscFunctionReturn(0);
1000785d1243SStefano Zampini }
1001785d1243SStefano Zampini 
100253cdbc3dSStefano Zampini /*@
100382ba6b80SStefano Zampini  PCBDDCGetNeumannBoundariesLocal - Get parallel IS for Neumann boundaries (in local ordering)
100453cdbc3dSStefano Zampini 
1005785d1243SStefano Zampini    Collective
100653cdbc3dSStefano Zampini 
100753cdbc3dSStefano Zampini    Input Parameters:
100828509bceSStefano Zampini .  pc - the preconditioning context
100953cdbc3dSStefano Zampini 
101053cdbc3dSStefano Zampini    Output Parameters:
101128509bceSStefano Zampini .  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
101253cdbc3dSStefano Zampini 
101353cdbc3dSStefano Zampini    Level: intermediate
101453cdbc3dSStefano Zampini 
101553cdbc3dSStefano Zampini    Notes:
10160f202f7eSStefano 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).
10170f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
101853cdbc3dSStefano Zampini 
1019db781477SPatrick Sanan .seealso: `PCBDDC`
102053cdbc3dSStefano Zampini @*/
102182ba6b80SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc,IS *NeumannBoundaries)
102253cdbc3dSStefano Zampini {
102353cdbc3dSStefano Zampini   PetscFunctionBegin;
102453cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1025cac4c232SBarry Smith   PetscUseMethod(pc,"PCBDDCGetNeumannBoundariesLocal_C",(PC,IS*),(pc,NeumannBoundaries));
10260c7d97c5SJed Brown   PetscFunctionReturn(0);
10270c7d97c5SJed Brown }
10281e6b0712SBarry Smith 
10291a83f524SJed Brown static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
103036e030ebSStefano Zampini {
103136e030ebSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1032da1bb401SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
103356282151SStefano Zampini   PetscBool      same_data = PETSC_FALSE;
103436e030ebSStefano Zampini 
103536e030ebSStefano Zampini   PetscFunctionBegin;
10368687889aSStefano Zampini   if (!nvtxs) {
103704194a47SStefano Zampini     if (copymode == PETSC_OWN_POINTER) {
10389566063dSJacob Faibussowitsch       PetscCall(PetscFree(xadj));
10399566063dSJacob Faibussowitsch       PetscCall(PetscFree(adjncy));
104004194a47SStefano Zampini     }
10419566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphResetCSR(mat_graph));
10428687889aSStefano Zampini     PetscFunctionReturn(0);
10438687889aSStefano Zampini   }
104466da6bd7Sstefano_zampini   if (mat_graph->nvtxs == nvtxs && mat_graph->freecsr) { /* we own the data */
104556282151SStefano Zampini     if (mat_graph->xadj == xadj && mat_graph->adjncy == adjncy) same_data = PETSC_TRUE;
104656282151SStefano Zampini     if (!same_data && mat_graph->xadj[nvtxs] == xadj[nvtxs]) {
10479566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(xadj,mat_graph->xadj,nvtxs+1,&same_data));
10482d505d7fSStefano Zampini       if (same_data) {
10499566063dSJacob Faibussowitsch         PetscCall(PetscArraycmp(adjncy,mat_graph->adjncy,xadj[nvtxs],&same_data));
10502d505d7fSStefano Zampini       }
105156282151SStefano Zampini     }
105256282151SStefano Zampini   }
105356282151SStefano Zampini   if (!same_data) {
1054674ae819SStefano Zampini     /* free old CSR */
10559566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphResetCSR(mat_graph));
1056674ae819SStefano Zampini     /* get CSR into graph structure */
1057da1bb401SStefano Zampini     if (copymode == PETSC_COPY_VALUES) {
10589566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nvtxs+1,&mat_graph->xadj));
10599566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(xadj[nvtxs],&mat_graph->adjncy));
10609566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(mat_graph->xadj,xadj,nvtxs+1));
10619566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(mat_graph->adjncy,adjncy,xadj[nvtxs]));
1062a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1063da1bb401SStefano Zampini     } else if (copymode == PETSC_OWN_POINTER) {
10641a83f524SJed Brown       mat_graph->xadj    = (PetscInt*)xadj;
10651a83f524SJed Brown       mat_graph->adjncy  = (PetscInt*)adjncy;
1066a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1067a1dbd327SStefano Zampini     } else if (copymode == PETSC_USE_POINTER) {
1068a1dbd327SStefano Zampini       mat_graph->xadj    = (PetscInt*)xadj;
1069a1dbd327SStefano Zampini       mat_graph->adjncy  = (PetscInt*)adjncy;
1070a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_FALSE;
107163a3b9bcSJacob Faibussowitsch     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %d",copymode);
1072575ad6abSStefano Zampini     mat_graph->nvtxs_csr = nvtxs;
107356282151SStefano Zampini     pcbddc->recompute_topography = PETSC_TRUE;
107456282151SStefano Zampini   }
107536e030ebSStefano Zampini   PetscFunctionReturn(0);
107636e030ebSStefano Zampini }
10771e6b0712SBarry Smith 
107836e030ebSStefano Zampini /*@
107954fffbccSStefano Zampini  PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local degrees of freedom.
108036e030ebSStefano Zampini 
108136e030ebSStefano Zampini    Not collective
108236e030ebSStefano Zampini 
108336e030ebSStefano Zampini    Input Parameters:
108454fffbccSStefano Zampini +  pc - the preconditioning context.
108554fffbccSStefano Zampini .  nvtxs - number of local vertices of the graph (i.e., the number of local dofs).
108654fffbccSStefano Zampini .  xadj, adjncy - the connectivity of the dofs in CSR format.
108754fffbccSStefano Zampini -  copymode - supported modes are PETSC_COPY_VALUES, PETSC_USE_POINTER or PETSC_OWN_POINTER.
108836e030ebSStefano Zampini 
108936e030ebSStefano Zampini    Level: intermediate
109036e030ebSStefano Zampini 
109195452b02SPatrick Sanan    Notes:
109295452b02SPatrick Sanan     A dof is considered connected with all local dofs if xadj[dof+1]-xadj[dof] == 1 and adjncy[xadj[dof]] is negative.
109336e030ebSStefano Zampini 
109416b07851SJed Brown .seealso: `PCBDDC`, `PetscCopyMode`
109536e030ebSStefano Zampini @*/
10961a83f524SJed Brown PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
109736e030ebSStefano Zampini {
10980a545947SLisandro Dalcin   void (*f)(void) = NULL;
109936e030ebSStefano Zampini 
110036e030ebSStefano Zampini   PetscFunctionBegin;
110136e030ebSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
11028687889aSStefano Zampini   if (nvtxs) {
1103674ae819SStefano Zampini     PetscValidIntPointer(xadj,3);
11041633d1f0SStefano Zampini     if (xadj[nvtxs]) PetscValidIntPointer(adjncy,4);
11058687889aSStefano Zampini   }
1106cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));
1107575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
11089566063dSJacob Faibussowitsch   PetscCall(PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f));
1109575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
11109566063dSJacob Faibussowitsch     PetscCall(PetscFree(xadj));
11119566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjncy));
1112da1bb401SStefano Zampini   }
111336e030ebSStefano Zampini   PetscFunctionReturn(0);
111436e030ebSStefano Zampini }
11151e6b0712SBarry Smith 
111663602bcaSStefano Zampini static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
111763602bcaSStefano Zampini {
111863602bcaSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
111963602bcaSStefano Zampini   PetscInt       i;
112056282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
112163602bcaSStefano Zampini 
112263602bcaSStefano Zampini   PetscFunctionBegin;
112356282151SStefano Zampini   if (pcbddc->n_ISForDofsLocal == n_is) {
112456282151SStefano Zampini     for (i=0;i<n_is;i++) {
112556282151SStefano Zampini       PetscBool isequalt;
11269566063dSJacob Faibussowitsch       PetscCall(ISEqual(ISForDofs[i],pcbddc->ISForDofsLocal[i],&isequalt));
112756282151SStefano Zampini       if (!isequalt) break;
112856282151SStefano Zampini     }
112956282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
113056282151SStefano Zampini   }
113156282151SStefano Zampini   for (i=0;i<n_is;i++) {
11329566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)ISForDofs[i]));
113356282151SStefano Zampini   }
113463602bcaSStefano Zampini   /* Destroy ISes if they were already set */
113563602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
11369566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i]));
113763602bcaSStefano Zampini   }
11389566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofsLocal));
1139a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
114063602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
11419566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&pcbddc->ISForDofs[i]));
114263602bcaSStefano Zampini   }
11439566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofs));
114463602bcaSStefano Zampini   pcbddc->n_ISForDofs = 0;
114563602bcaSStefano Zampini   /* allocate space then set */
1146d02579f5SStefano Zampini   if (n_is) {
11479566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n_is,&pcbddc->ISForDofsLocal));
1148d02579f5SStefano Zampini   }
114963602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
115063602bcaSStefano Zampini     pcbddc->ISForDofsLocal[i] = ISForDofs[i];
115163602bcaSStefano Zampini   }
115263602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = n_is;
115363602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
115456282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
115563602bcaSStefano Zampini   PetscFunctionReturn(0);
115663602bcaSStefano Zampini }
115763602bcaSStefano Zampini 
115863602bcaSStefano Zampini /*@
115963602bcaSStefano Zampini  PCBDDCSetDofsSplittingLocal - Set index sets defining fields of the local subdomain matrix
116063602bcaSStefano Zampini 
116163602bcaSStefano Zampini    Collective
116263602bcaSStefano Zampini 
116363602bcaSStefano Zampini    Input Parameters:
116463602bcaSStefano Zampini +  pc - the preconditioning context
11650f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
11660f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in local ordering
116763602bcaSStefano Zampini 
116863602bcaSStefano Zampini    Level: intermediate
116963602bcaSStefano Zampini 
11700f202f7eSStefano Zampini    Notes:
11710f202f7eSStefano Zampini      n_is should be the same among processes. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
117263602bcaSStefano Zampini 
1173db781477SPatrick Sanan .seealso: `PCBDDC`
117463602bcaSStefano Zampini @*/
117563602bcaSStefano Zampini PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc,PetscInt n_is, IS ISForDofs[])
117663602bcaSStefano Zampini {
117763602bcaSStefano Zampini   PetscInt       i;
117863602bcaSStefano Zampini 
117963602bcaSStefano Zampini   PetscFunctionBegin;
118063602bcaSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
118163602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
118263602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
118363602bcaSStefano Zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
118463602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
118563602bcaSStefano Zampini   }
1186cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetDofsSplittingLocal_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));
118763602bcaSStefano Zampini   PetscFunctionReturn(0);
118863602bcaSStefano Zampini }
118963602bcaSStefano Zampini 
11909c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
11919c0446d6SStefano Zampini {
11929c0446d6SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
11939c0446d6SStefano Zampini   PetscInt       i;
119456282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
11959c0446d6SStefano Zampini 
11969c0446d6SStefano Zampini   PetscFunctionBegin;
119756282151SStefano Zampini   if (pcbddc->n_ISForDofs == n_is) {
119856282151SStefano Zampini     for (i=0;i<n_is;i++) {
119956282151SStefano Zampini       PetscBool isequalt;
12009566063dSJacob Faibussowitsch       PetscCall(ISEqual(ISForDofs[i],pcbddc->ISForDofs[i],&isequalt));
120156282151SStefano Zampini       if (!isequalt) break;
120256282151SStefano Zampini     }
120356282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
120456282151SStefano Zampini   }
120556282151SStefano Zampini   for (i=0;i<n_is;i++) {
12069566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)ISForDofs[i]));
120756282151SStefano Zampini   }
1208da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
12099c0446d6SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
12109566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&pcbddc->ISForDofs[i]));
12119c0446d6SStefano Zampini   }
12129566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofs));
1213a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
121463602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
12159566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&pcbddc->ISForDofsLocal[i]));
121663602bcaSStefano Zampini   }
12179566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcbddc->ISForDofsLocal));
121863602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = 0;
1219da1bb401SStefano Zampini   /* allocate space then set */
1220d02579f5SStefano Zampini   if (n_is) {
12219566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(n_is,&pcbddc->ISForDofs));
1222d02579f5SStefano Zampini   }
12239c0446d6SStefano Zampini   for (i=0;i<n_is;i++) {
1224da1bb401SStefano Zampini     pcbddc->ISForDofs[i] = ISForDofs[i];
12259c0446d6SStefano Zampini   }
12269c0446d6SStefano Zampini   pcbddc->n_ISForDofs = n_is;
122763602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
122856282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
12299c0446d6SStefano Zampini   PetscFunctionReturn(0);
12309c0446d6SStefano Zampini }
12311e6b0712SBarry Smith 
12329c0446d6SStefano Zampini /*@
123363602bcaSStefano Zampini  PCBDDCSetDofsSplitting - Set index sets defining fields of the global matrix
12349c0446d6SStefano Zampini 
123563602bcaSStefano Zampini    Collective
12369c0446d6SStefano Zampini 
12379c0446d6SStefano Zampini    Input Parameters:
12389c0446d6SStefano Zampini +  pc - the preconditioning context
12390f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
12400f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in global ordering
12419c0446d6SStefano Zampini 
12429c0446d6SStefano Zampini    Level: intermediate
12439c0446d6SStefano Zampini 
12440f202f7eSStefano Zampini    Notes:
12450f202f7eSStefano Zampini      Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
12469c0446d6SStefano Zampini 
1247db781477SPatrick Sanan .seealso: `PCBDDC`
12489c0446d6SStefano Zampini @*/
12499c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
12509c0446d6SStefano Zampini {
12512b510759SStefano Zampini   PetscInt       i;
12529c0446d6SStefano Zampini 
12539c0446d6SStefano Zampini   PetscFunctionBegin;
12549c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
125563602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
12562b510759SStefano Zampini   for (i=0;i<n_is;i++) {
125763602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
1258a011d5a7Sstefano_zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
12592b510759SStefano Zampini   }
1260cac4c232SBarry Smith   PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));
12619c0446d6SStefano Zampini   PetscFunctionReturn(0);
12629c0446d6SStefano Zampini }
1263906d46d4SStefano Zampini 
1264534831adSStefano Zampini /*
1265534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
1266534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
12679c0446d6SStefano Zampini 
1268534831adSStefano Zampini    Input Parameter:
1269966d8056SPierre Jolivet +  pc - the preconditioner context
1270534831adSStefano Zampini 
1271534831adSStefano Zampini    Application Interface Routine: PCPreSolve()
1272534831adSStefano Zampini 
1273534831adSStefano Zampini    Notes:
1274534831adSStefano Zampini      The interface routine PCPreSolve() is not usually called directly by
1275534831adSStefano Zampini    the user, but instead is called by KSPSolve().
1276534831adSStefano Zampini */
1277534831adSStefano Zampini static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1278534831adSStefano Zampini {
1279534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1280534831adSStefano Zampini   PC_IS          *pcis = (PC_IS*)(pc->data);
12813972b0daSStefano Zampini   Vec            used_vec;
1282fcb54b1cSPierre Jolivet   PetscBool      iscg, save_rhs = PETSC_TRUE, benign_correction_computed;
1283534831adSStefano Zampini 
1284534831adSStefano Zampini   PetscFunctionBegin;
12851f4df5f7SStefano Zampini   /* if we are working with CG, one dirichlet solve can be avoided during Krylov iterations */
128685c4d303SStefano Zampini   if (ksp) {
1287fcb54b1cSPierre Jolivet     PetscCall(PetscObjectTypeCompareAny((PetscObject)ksp,&iscg,KSPCG,KSPGROPPCG,KSPPIPECG,KSPPIPELCG,KSPPIPECGRR,""));
12883bf6e316SStefano Zampini     if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || !iscg || pc->mat != pc->pmat) {
12899566063dSJacob Faibussowitsch       PetscCall(PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE));
129085c4d303SStefano Zampini     }
129185c4d303SStefano Zampini   }
12923bf6e316SStefano Zampini   if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || pc->mat != pc->pmat) {
12939566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE));
1294fc17d649SStefano Zampini   }
12951f4df5f7SStefano Zampini 
129685c4d303SStefano Zampini   /* Creates parallel work vectors used in presolve */
129762a6ff1dSStefano Zampini   if (!pcbddc->original_rhs) {
12989566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs));
129962a6ff1dSStefano Zampini   }
130062a6ff1dSStefano Zampini   if (!pcbddc->temp_solution) {
13019566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution));
130262a6ff1dSStefano Zampini   }
13038d00608fSStefano Zampini 
130427b6a85dSStefano Zampini   pcbddc->temp_solution_used = PETSC_FALSE;
13053972b0daSStefano Zampini   if (x) {
13069566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)x));
13073972b0daSStefano Zampini     used_vec = x;
13088d00608fSStefano Zampini   } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */
13099566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)pcbddc->temp_solution));
13103972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
13119566063dSJacob Faibussowitsch     PetscCall(VecSet(used_vec,0.0));
131227b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
13139566063dSJacob Faibussowitsch     PetscCall(VecCopy(rhs,pcbddc->original_rhs));
1314266e20e9SStefano Zampini     save_rhs = PETSC_FALSE;
1315266e20e9SStefano Zampini     pcbddc->eliminate_dirdofs = PETSC_TRUE;
13163972b0daSStefano Zampini   }
13178efcfb23SStefano Zampini 
13188efcfb23SStefano Zampini   /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */
13193972b0daSStefano Zampini   if (ksp) {
1320a0cb1b98SStefano Zampini     /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */
13219566063dSJacob Faibussowitsch     PetscCall(KSPGetInitialGuessNonzero(ksp,&pcbddc->ksp_guess_nonzero));
13228efcfb23SStefano Zampini     if (!pcbddc->ksp_guess_nonzero) {
13239566063dSJacob Faibussowitsch       PetscCall(VecSet(used_vec,0.0));
13243972b0daSStefano Zampini     }
13253972b0daSStefano Zampini   }
13263308cffdSStefano Zampini 
13278d00608fSStefano Zampini   pcbddc->rhs_change = PETSC_FALSE;
13283972b0daSStefano Zampini   /* Take into account zeroed rows -> change rhs and store solution removed */
132970c64980SStefano Zampini   if (rhs && pcbddc->eliminate_dirdofs) {
13303975b054SStefano Zampini     IS dirIS = NULL;
13313975b054SStefano Zampini 
1332a07ea27aSStefano Zampini     /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */
13339566063dSJacob Faibussowitsch     PetscCall(PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS));
13343975b054SStefano Zampini     if (dirIS) {
1335906d46d4SStefano Zampini       Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
1336785d1243SStefano Zampini       PetscInt          dirsize,i,*is_indices;
13372b095fd8SStefano Zampini       PetscScalar       *array_x;
13382b095fd8SStefano Zampini       const PetscScalar *array_diagonal;
1339785d1243SStefano Zampini 
13409566063dSJacob Faibussowitsch       PetscCall(MatGetDiagonal(pc->pmat,pcis->vec1_global));
13419566063dSJacob Faibussowitsch       PetscCall(VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global));
13429566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD));
13439566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD));
13449566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD));
13459566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD));
13469566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(dirIS,&dirsize));
13479566063dSJacob Faibussowitsch       PetscCall(VecGetArray(pcis->vec1_N,&array_x));
13489566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(pcis->vec2_N,&array_diagonal));
13499566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(dirIS,(const PetscInt**)&is_indices));
13502fa5cd67SKarl Rupp       for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
13519566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(dirIS,(const PetscInt**)&is_indices));
13529566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(pcis->vec2_N,&array_diagonal));
13539566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(pcis->vec1_N,&array_x));
13549566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE));
13559566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE));
13568d00608fSStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
13579566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&dirIS));
13588efcfb23SStefano Zampini     }
1359a07ea27aSStefano Zampini   }
1360b76ba322SStefano Zampini 
13618efcfb23SStefano Zampini   /* remove the computed solution or the initial guess from the rhs */
13628d00608fSStefano Zampini   if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero)) {
136327b6a85dSStefano Zampini     /* save the original rhs */
136427b6a85dSStefano Zampini     if (save_rhs) {
13659566063dSJacob Faibussowitsch       PetscCall(VecSwap(rhs,pcbddc->original_rhs));
136627b6a85dSStefano Zampini       save_rhs = PETSC_FALSE;
13678d00608fSStefano Zampini     }
13688d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
13699566063dSJacob Faibussowitsch     PetscCall(VecScale(used_vec,-1.0));
13709566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(pc->mat,used_vec,pcbddc->original_rhs,rhs));
13719566063dSJacob Faibussowitsch     PetscCall(VecScale(used_vec,-1.0));
13729566063dSJacob Faibussowitsch     PetscCall(VecCopy(used_vec,pcbddc->temp_solution));
137327b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
13747acc28cbSStefano Zampini     if (ksp) {
13759566063dSJacob Faibussowitsch       PetscCall(KSPSetInitialGuessNonzero(ksp,PETSC_FALSE));
13767acc28cbSStefano Zampini     }
13773308cffdSStefano Zampini   }
13789566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&used_vec));
1379b76ba322SStefano Zampini 
1380fc17d649SStefano Zampini   /* compute initial vector in benign space if needed
138127b6a85dSStefano Zampini      and remove non-benign solution from the rhs */
138227b6a85dSStefano Zampini   benign_correction_computed = PETSC_FALSE;
138308af2428SStefano Zampini   if (rhs && pcbddc->benign_compute_correction && (pcbddc->benign_have_null || pcbddc->benign_apply_coarse_only)) {
13841f4df5f7SStefano Zampini     /* compute u^*_h using ideas similar to those in Xuemin Tu's PhD thesis (see Section 4.8.1)
13851f4df5f7SStefano Zampini        Recursively apply BDDC in the multilevel case */
13860369aaf7SStefano Zampini     if (!pcbddc->benign_vec) {
13879566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(rhs,&pcbddc->benign_vec));
13880369aaf7SStefano Zampini     }
1389c69e9cc1SStefano Zampini     /* keep applying coarse solver unless we no longer have benign subdomains */
1390c69e9cc1SStefano Zampini     pcbddc->benign_apply_coarse_only = pcbddc->benign_have_null ? PETSC_TRUE : PETSC_FALSE;
139127b6a85dSStefano Zampini     if (!pcbddc->benign_skip_correction) {
13929566063dSJacob Faibussowitsch       PetscCall(PCApply_BDDC(pc,rhs,pcbddc->benign_vec));
13933bca92a6SStefano Zampini       benign_correction_computed = PETSC_TRUE;
13941f4df5f7SStefano Zampini       if (pcbddc->temp_solution_used) {
13959566063dSJacob Faibussowitsch         PetscCall(VecAXPY(pcbddc->temp_solution,1.0,pcbddc->benign_vec));
13961f4df5f7SStefano Zampini       }
13979566063dSJacob Faibussowitsch       PetscCall(VecScale(pcbddc->benign_vec,-1.0));
139827b6a85dSStefano Zampini       /* store the original rhs if not done earlier */
139927b6a85dSStefano Zampini       if (save_rhs) {
14009566063dSJacob Faibussowitsch         PetscCall(VecSwap(rhs,pcbddc->original_rhs));
140192e3dcfbSStefano Zampini       }
140227b6a85dSStefano Zampini       if (pcbddc->rhs_change) {
14039566063dSJacob Faibussowitsch         PetscCall(MatMultAdd(pc->mat,pcbddc->benign_vec,rhs,rhs));
140427b6a85dSStefano Zampini       } else {
14059566063dSJacob Faibussowitsch         PetscCall(MatMultAdd(pc->mat,pcbddc->benign_vec,pcbddc->original_rhs,rhs));
140627b6a85dSStefano Zampini       }
14070369aaf7SStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
140827b6a85dSStefano Zampini     }
140927b6a85dSStefano Zampini     pcbddc->benign_apply_coarse_only = PETSC_FALSE;
14104df7a6bfSStefano Zampini   } else {
14119566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&pcbddc->benign_vec));
14120369aaf7SStefano Zampini   }
14132d4c4fecSStefano Zampini 
14142d4c4fecSStefano Zampini   /* dbg output */
1415a198735bSStefano Zampini   if (pcbddc->dbg_flag && benign_correction_computed) {
14161f4df5f7SStefano Zampini     Vec v;
1417c69e9cc1SStefano Zampini 
14189566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_global,&v));
1419c69e9cc1SStefano Zampini     if (pcbddc->ChangeOfBasisMatrix) {
14209566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,v));
1421c69e9cc1SStefano Zampini     } else {
14229566063dSJacob Faibussowitsch       PetscCall(VecCopy(rhs,v));
1423c69e9cc1SStefano Zampini     }
14249566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc,v,PETSC_TRUE));
142563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"LEVEL %" PetscInt_FMT ": is the correction benign?\n",pcbddc->current_level));
14269566063dSJacob Faibussowitsch     PetscCall(PetscScalarView(pcbddc->benign_n,pcbddc->benign_p0,pcbddc->dbg_viewer));
14279566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(pcbddc->dbg_viewer));
14289566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&v));
14291f4df5f7SStefano Zampini   }
14300369aaf7SStefano Zampini 
14310369aaf7SStefano Zampini   /* set initial guess if using PCG */
14328ae0ca82SStefano Zampini   pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
14330369aaf7SStefano Zampini   if (x && pcbddc->use_exact_dirichlet_trick) {
14349566063dSJacob Faibussowitsch     PetscCall(VecSet(x,0.0));
14351dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
143627b6a85dSStefano Zampini       if (benign_correction_computed) { /* we have already saved the changed rhs */
14379566063dSJacob Faibussowitsch         PetscCall(VecLockReadPop(pcis->vec1_global));
14381dd7afcfSStefano Zampini       } else {
14399566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,pcis->vec1_global));
14401dd7afcfSStefano Zampini       }
14419566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
14429566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
14431dd7afcfSStefano Zampini     } else {
14449566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
14459566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
14461dd7afcfSStefano Zampini     }
14479566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
14489566063dSJacob Faibussowitsch     PetscCall(KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D));
14499566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
14509566063dSJacob Faibussowitsch     PetscCall(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D));
14511dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
14529566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_global,0.));
14539566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE));
14549566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE));
14559566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x));
14561dd7afcfSStefano Zampini     } else {
14579566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE));
14589566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE));
14591dd7afcfSStefano Zampini     }
14600369aaf7SStefano Zampini     if (ksp) {
14619566063dSJacob Faibussowitsch       PetscCall(KSPSetInitialGuessNonzero(ksp,PETSC_TRUE));
14620369aaf7SStefano Zampini     }
14638ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_TRUE;
1464266e20e9SStefano Zampini   } else if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior && benign_correction_computed && pcbddc->use_exact_dirichlet_trick) {
14659566063dSJacob Faibussowitsch     PetscCall(VecLockReadPop(pcis->vec1_global));
14660369aaf7SStefano Zampini   }
1467534831adSStefano Zampini   PetscFunctionReturn(0);
1468534831adSStefano Zampini }
1469906d46d4SStefano Zampini 
1470534831adSStefano Zampini /*
1471534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
1472534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
1473534831adSStefano Zampini 
1474534831adSStefano Zampini    Input Parameter:
1475966d8056SPierre Jolivet +  pc - the preconditioner context
1476534831adSStefano Zampini 
1477534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
1478534831adSStefano Zampini 
1479534831adSStefano Zampini    Notes:
1480534831adSStefano Zampini      The interface routine PCPostSolve() is not usually called directly by
1481534831adSStefano Zampini      the user, but instead is called by KSPSolve().
1482534831adSStefano Zampini */
1483534831adSStefano Zampini static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1484534831adSStefano Zampini {
1485534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1486534831adSStefano Zampini 
1487534831adSStefano Zampini   PetscFunctionBegin;
14883972b0daSStefano Zampini   /* add solution removed in presolve */
14896bcfc461SStefano Zampini   if (x && pcbddc->rhs_change) {
149027b6a85dSStefano Zampini     if (pcbddc->temp_solution_used) {
14919566063dSJacob Faibussowitsch       PetscCall(VecAXPY(x,1.0,pcbddc->temp_solution));
1492af140850Sstefano_zampini     } else if (pcbddc->benign_compute_correction && pcbddc->benign_vec) {
14939566063dSJacob Faibussowitsch       PetscCall(VecAXPY(x,-1.0,pcbddc->benign_vec));
14943425bc38SStefano Zampini     }
1495af140850Sstefano_zampini     /* restore to original state (not for FETI-DP) */
1496af140850Sstefano_zampini     if (ksp) pcbddc->temp_solution_used = PETSC_FALSE;
149727b6a85dSStefano Zampini   }
149827b6a85dSStefano Zampini 
1499266e20e9SStefano Zampini   /* restore rhs to its original state (not needed for FETI-DP) */
15008d00608fSStefano Zampini   if (rhs && pcbddc->rhs_change) {
15019566063dSJacob Faibussowitsch     PetscCall(VecSwap(rhs,pcbddc->original_rhs));
15028d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_FALSE;
1503af140850Sstefano_zampini   }
15048efcfb23SStefano Zampini   /* restore ksp guess state */
15058efcfb23SStefano Zampini   if (ksp) {
15069566063dSJacob Faibussowitsch     PetscCall(KSPSetInitialGuessNonzero(ksp,pcbddc->ksp_guess_nonzero));
15078ae0ca82SStefano Zampini     /* reset flag for exact dirichlet trick */
15088ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
1509af140850Sstefano_zampini   }
1510534831adSStefano Zampini   PetscFunctionReturn(0);
1511534831adSStefano Zampini }
1512af140850Sstefano_zampini 
15130c7d97c5SJed Brown /*
15140c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
15150c7d97c5SJed Brown                   by setting data structures and options.
15160c7d97c5SJed Brown 
15170c7d97c5SJed Brown    Input Parameter:
151853cdbc3dSStefano Zampini +  pc - the preconditioner context
15190c7d97c5SJed Brown 
15200c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
15210c7d97c5SJed Brown 
15220c7d97c5SJed Brown    Notes:
15230c7d97c5SJed Brown      The interface routine PCSetUp() is not usually called directly by
15240c7d97c5SJed Brown      the user, but instead is called by PCApply() if necessary.
15250c7d97c5SJed Brown */
152653cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
15270c7d97c5SJed Brown {
15280c7d97c5SJed Brown   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1529c703fcc7SStefano Zampini   PCBDDCSubSchurs sub_schurs;
15305e8657edSStefano Zampini   Mat_IS*         matis;
153108122e43SStefano Zampini   MatNullSpace    nearnullspace;
153235509ce9Sstefano_zampini   Mat             lA;
153335509ce9Sstefano_zampini   IS              lP,zerodiag = NULL;
153491e8d312SStefano Zampini   PetscInt        nrows,ncols;
153586bfa4cfSStefano Zampini   PetscMPIInt     size;
1536c703fcc7SStefano Zampini   PetscBool       computesubschurs;
15378de1fae6SStefano Zampini   PetscBool       computeconstraintsmatrix;
15383b03f7bbSStefano Zampini   PetscBool       new_nearnullspace_provided,ismatis,rl;
15390c7d97c5SJed Brown 
15400c7d97c5SJed Brown   PetscFunctionBegin;
15419566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat,MATIS,&ismatis));
154228b400f6SJacob Faibussowitsch   PetscCheck(ismatis,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner requires matrix of type MATIS");
15439566063dSJacob Faibussowitsch   PetscCall(MatGetSize(pc->pmat,&nrows,&ncols));
15447827d75bSBarry Smith   PetscCheck(nrows == ncols,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCBDDC preconditioner requires a square preconditioning matrix");
15459566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size));
154686bfa4cfSStefano Zampini 
15475e8657edSStefano Zampini   matis = (Mat_IS*)pc->pmat->data;
1548f4ddd8eeSStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */
15493b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
155071582508SStefano Zampini      Also, BDDC builds its own KSP for the Dirichlet problem */
15513b03f7bbSStefano Zampini   rl = pcbddc->recompute_topography;
15523b03f7bbSStefano Zampini   if (!pc->setupcalled || pc->flag == DIFFERENT_NONZERO_PATTERN) rl = PETSC_TRUE;
15531c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&rl,&pcbddc->recompute_topography,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc)));
1554c83e1ba7SStefano Zampini   if (pcbddc->recompute_topography) {
1555c83e1ba7SStefano Zampini     pcbddc->graphanalyzed    = PETSC_FALSE;
1556c83e1ba7SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1557c83e1ba7SStefano Zampini   } else {
15588de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_FALSE;
1559c83e1ba7SStefano Zampini   }
1560b087196eSStefano Zampini 
1561b087196eSStefano Zampini   /* check parameters' compatibility */
1562b7ab4a40SStefano Zampini   if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE;
1563bd2a564bSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_threshold[0] != 0.0 || pcbddc->adaptive_threshold[1] != 0.0);
156486bfa4cfSStefano Zampini   pcbddc->use_deluxe_scaling   = (PetscBool)(pcbddc->use_deluxe_scaling && size > 1);
156586bfa4cfSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_selection && size > 1);
1566bf3a8328SStefano Zampini   pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined);
1567862806e4SStefano Zampini   if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE;
1568862806e4SStefano Zampini 
15695a95e1ceSStefano Zampini   computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling);
157016909a7fSStefano Zampini 
157171582508SStefano Zampini   /* activate all connected components if the netflux has been requested */
1572bb05f991SStefano Zampini   if (pcbddc->compute_nonetflux) {
1573bb05f991SStefano Zampini     pcbddc->use_vertices = PETSC_TRUE;
1574bb05f991SStefano Zampini     pcbddc->use_edges    = PETSC_TRUE;
1575bb05f991SStefano Zampini     pcbddc->use_faces    = PETSC_TRUE;
1576bb05f991SStefano Zampini   }
1577bb05f991SStefano Zampini 
1578f4ddd8eeSStefano Zampini   /* Get stdout for dbg */
157970cf5478SStefano Zampini   if (pcbddc->dbg_flag) {
158070cf5478SStefano Zampini     if (!pcbddc->dbg_viewer) {
158158a03d70SStefano Zampini       pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc));
1582f4ddd8eeSStefano Zampini     }
15839566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer));
15849566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2*pcbddc->current_level));
1585f4ddd8eeSStefano Zampini   }
1586f4ddd8eeSStefano Zampini 
1587c703fcc7SStefano Zampini   /* process topology information */
15889566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Topology[pcbddc->current_level],pc,0,0,0));
158971582508SStefano Zampini   if (pcbddc->recompute_topography) {
15909566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeLocalTopologyInfo(pc));
1591c703fcc7SStefano Zampini     if (pcbddc->discretegradient) {
15929566063dSJacob Faibussowitsch       PetscCall(PCBDDCNedelecSupport(pc));
1593a13144ffSStefano Zampini     }
1594c703fcc7SStefano Zampini   }
15954f819b78SStefano Zampini   if (pcbddc->corner_selected) pcbddc->use_vertices = PETSC_TRUE;
1596a13144ffSStefano Zampini 
1597c703fcc7SStefano Zampini   /* change basis if requested by the user */
15985e8657edSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) {
15995e8657edSStefano Zampini     /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */
16005e8657edSStefano Zampini     pcbddc->use_change_of_basis = PETSC_FALSE;
16019566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeLocalMatrix(pc,pcbddc->user_ChangeOfBasisMatrix));
16025e8657edSStefano Zampini   } else {
16039566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcbddc->local_mat));
16049566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)matis->A));
16055e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
1606d16cbb6bSStefano Zampini   }
1607d16cbb6bSStefano Zampini 
16084f1b2e48SStefano Zampini   /*
1609c703fcc7SStefano Zampini      Compute change of basis on local pressures (aka zerodiag dofs) with the benign trick
16104f1b2e48SStefano Zampini      This should come earlier then PCISSetUp for extracting the correct subdomain matrices
16114f1b2e48SStefano Zampini   */
16129566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignShellMat(pc,PETSC_TRUE));
1613d16cbb6bSStefano Zampini   if (pcbddc->benign_saddle_point) {
16149f47a83aSStefano Zampini     PC_IS* pcis = (PC_IS*)pc->data;
16159f47a83aSStefano Zampini 
161605b28244SStefano Zampini     if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE;
16173b03f7bbSStefano Zampini     /* detect local saddle point and change the basis in pcbddc->local_mat */
16189566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignDetectSaddlePoint(pc,(PetscBool)(!pcbddc->recompute_topography),&zerodiag));
1619a3df083aSStefano Zampini     /* pop B0 mat from local mat */
16209566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE));
16211dd7afcfSStefano Zampini     /* give pcis a hint to not reuse submatrices during PCISCreate */
16221dd7afcfSStefano Zampini     if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) {
16231dd7afcfSStefano Zampini       if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) {
16241dd7afcfSStefano Zampini         pcis->reusesubmatrices = PETSC_FALSE;
16251dd7afcfSStefano Zampini       } else {
1626a3df083aSStefano Zampini         pcis->reusesubmatrices = PETSC_TRUE;
16271dd7afcfSStefano Zampini       }
1628a3df083aSStefano Zampini     } else {
16299f47a83aSStefano Zampini       pcis->reusesubmatrices = PETSC_FALSE;
1630674ae819SStefano Zampini     }
1631a3df083aSStefano Zampini   }
163227b6a85dSStefano Zampini 
16338037d520SStefano Zampini   /* propagate relevant information */
163406a4e24aSStefano Zampini   if (matis->A->symmetric_set) {
16359566063dSJacob Faibussowitsch     PetscCall(MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric));
163606a4e24aSStefano Zampini   }
163706a4e24aSStefano Zampini   if (matis->A->spd_set) {
16389566063dSJacob Faibussowitsch     PetscCall(MatSetOption(pcbddc->local_mat,MAT_SPD,matis->A->spd));
163906a4e24aSStefano Zampini   }
1640e496cd5dSStefano Zampini 
16415e8657edSStefano Zampini   /* Set up all the "iterative substructuring" common block without computing solvers */
16425e8657edSStefano Zampini   {
16435e8657edSStefano Zampini     Mat temp_mat;
16445e8657edSStefano Zampini 
16455e8657edSStefano Zampini     temp_mat = matis->A;
16465e8657edSStefano Zampini     matis->A = pcbddc->local_mat;
16479566063dSJacob Faibussowitsch     PetscCall(PCISSetUp(pc,PETSC_TRUE,PETSC_FALSE));
16485e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
16495e8657edSStefano Zampini     matis->A = temp_mat;
16505e8657edSStefano Zampini   }
1651684f6988SStefano Zampini 
165281d14e9dSStefano Zampini   /* Analyze interface */
165364ac59b8SStefano Zampini   if (!pcbddc->graphanalyzed) {
16549566063dSJacob Faibussowitsch     PetscCall(PCBDDCAnalyzeInterface(pc));
16558de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1656345ecf6cSStefano Zampini     if (pcbddc->adaptive_selection && !pcbddc->use_deluxe_scaling && !pcbddc->mat_graph->twodim) {
16574247aa23Sstefano_zampini       SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot compute the adaptive primal space for a problem with 3D edges without deluxe scaling");
1658345ecf6cSStefano Zampini     }
1659a198735bSStefano Zampini     if (pcbddc->compute_nonetflux) {
1660669cc0f4SStefano Zampini       MatNullSpace nnfnnsp;
1661669cc0f4SStefano Zampini 
166228b400f6SJacob Faibussowitsch       PetscCheck(pcbddc->divudotp,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Missing divudotp operator");
16639566063dSJacob Faibussowitsch       PetscCall(PCBDDCComputeNoNetFlux(pc->pmat,pcbddc->divudotp,pcbddc->divudotp_trans,pcbddc->divudotp_vl2l,pcbddc->mat_graph,&nnfnnsp));
166471582508SStefano Zampini       /* TODO what if a nearnullspace is already attached? */
16658037d520SStefano Zampini       if (nnfnnsp) {
16669566063dSJacob Faibussowitsch         PetscCall(MatSetNearNullSpace(pc->pmat,nnfnnsp));
16679566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceDestroy(&nnfnnsp));
1668669cc0f4SStefano Zampini       }
1669674ae819SStefano Zampini     }
16708037d520SStefano Zampini   }
16719566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Topology[pcbddc->current_level],pc,0,0,0));
1672fb8d54d4SStefano Zampini 
16735408967cSStefano Zampini   /* check existence of a divergence free extension, i.e.
16745408967cSStefano Zampini      b(v_I,p_0) = 0 for all v_I (raise error if not).
16755408967cSStefano Zampini      Also, check that PCBDDCBenignGetOrSetP0 works */
1676ff1f7e73Sstefano_zampini   if (pcbddc->benign_saddle_point && pcbddc->dbg_flag > 1) {
16779566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignCheck(pc,zerodiag));
167809f581a4SStefano Zampini   }
16799566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&zerodiag));
168006f24817SStefano Zampini 
1681b96c3477SStefano Zampini   /* Setup local dirichlet solver ksp_D and sub_schurs solvers */
1682c703fcc7SStefano Zampini   if (computesubschurs && pcbddc->recompute_topography) {
16839566063dSJacob Faibussowitsch     PetscCall(PCBDDCInitSubSchurs(pc));
1684b1b3d7a2SStefano Zampini   }
16859d54b7f4SStefano Zampini   /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/
16869d54b7f4SStefano Zampini   if (!pcbddc->use_deluxe_scaling) {
16879566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingSetUp(pc));
16889d54b7f4SStefano Zampini   }
1689c703fcc7SStefano Zampini 
1690c703fcc7SStefano Zampini   /* finish setup solvers and do adaptive selection of constraints */
1691b334f244SStefano Zampini   sub_schurs = pcbddc->sub_schurs;
1692b334f244SStefano Zampini   if (sub_schurs && sub_schurs->schur_explicit) {
16932070dbb6SStefano Zampini     if (computesubschurs) {
16949566063dSJacob Faibussowitsch       PetscCall(PCBDDCSetUpSubSchurs(pc));
16952070dbb6SStefano Zampini     }
16969566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE));
1697d5574798SStefano Zampini   } else {
16989566063dSJacob Faibussowitsch     PetscCall(PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE));
16992070dbb6SStefano Zampini     if (computesubschurs) {
17009566063dSJacob Faibussowitsch       PetscCall(PCBDDCSetUpSubSchurs(pc));
1701d5574798SStefano Zampini     }
17022070dbb6SStefano Zampini   }
170308122e43SStefano Zampini   if (pcbddc->adaptive_selection) {
17049566063dSJacob Faibussowitsch     PetscCall(PCBDDCAdaptiveSelection(pc));
17058de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1706b7eb3628SStefano Zampini   }
1707684f6988SStefano Zampini 
1708f4ddd8eeSStefano Zampini   /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */
1709fb8d54d4SStefano Zampini   new_nearnullspace_provided = PETSC_FALSE;
17109566063dSJacob Faibussowitsch   PetscCall(MatGetNearNullSpace(pc->pmat,&nearnullspace));
1711f4ddd8eeSStefano Zampini   if (pcbddc->onearnullspace) { /* already used nearnullspace */
1712f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* near null space attached to mat has been destroyed */
1713f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1714f4ddd8eeSStefano Zampini     } else {
1715f4ddd8eeSStefano Zampini       /* determine if the two nullspaces are different (should be lightweight) */
1716f4ddd8eeSStefano Zampini       if (nearnullspace != pcbddc->onearnullspace) {
1717f4ddd8eeSStefano Zampini         new_nearnullspace_provided = PETSC_TRUE;
1718165b64e2SStefano Zampini       } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */
1719f4ddd8eeSStefano Zampini         PetscInt         i;
1720165b64e2SStefano Zampini         const Vec        *nearnullvecs;
1721165b64e2SStefano Zampini         PetscObjectState state;
1722165b64e2SStefano Zampini         PetscInt         nnsp_size;
17239566063dSJacob Faibussowitsch         PetscCall(MatNullSpaceGetVecs(nearnullspace,NULL,&nnsp_size,&nearnullvecs));
1724f4ddd8eeSStefano Zampini         for (i=0;i<nnsp_size;i++) {
17259566063dSJacob Faibussowitsch           PetscCall(PetscObjectStateGet((PetscObject)nearnullvecs[i],&state));
1726165b64e2SStefano Zampini           if (pcbddc->onearnullvecs_state[i] != state) {
1727f4ddd8eeSStefano Zampini             new_nearnullspace_provided = PETSC_TRUE;
1728f4ddd8eeSStefano Zampini             break;
1729f4ddd8eeSStefano Zampini           }
1730f4ddd8eeSStefano Zampini         }
1731f4ddd8eeSStefano Zampini       }
1732f4ddd8eeSStefano Zampini     }
1733f4ddd8eeSStefano Zampini   } else {
1734f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* both nearnullspaces are null */
1735f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_FALSE;
1736f4ddd8eeSStefano Zampini     } else { /* nearnullspace attached later */
1737f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1738f4ddd8eeSStefano Zampini     }
1739f4ddd8eeSStefano Zampini   }
1740f4ddd8eeSStefano Zampini 
1741f4ddd8eeSStefano Zampini   /* Setup constraints and related work vectors */
1742727cdba6SStefano Zampini   /* reset primal space flags */
17439566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_LocalWork[pcbddc->current_level],pc,0,0,0));
1744f4ddd8eeSStefano Zampini   pcbddc->new_primal_space = PETSC_FALSE;
1745727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_FALSE;
17468de1fae6SStefano Zampini   if (computeconstraintsmatrix || new_nearnullspace_provided) {
1747727cdba6SStefano Zampini     /* It also sets the primal space flags */
17489566063dSJacob Faibussowitsch     PetscCall(PCBDDCConstraintsSetUp(pc));
17499543d0ffSStefano Zampini   }
1750e7b262bdSStefano Zampini   /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */
17519566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetUpLocalWorkVectors(pc));
17525e8657edSStefano Zampini 
17535e8657edSStefano Zampini   if (pcbddc->use_change_of_basis) {
17545e8657edSStefano Zampini     PC_IS *pcis = (PC_IS*)(pc->data);
17555e8657edSStefano Zampini 
17569566063dSJacob Faibussowitsch     PetscCall(PCBDDCComputeLocalMatrix(pc,pcbddc->ChangeOfBasisMatrix));
17574f1b2e48SStefano Zampini     if (pcbddc->benign_change) {
17589566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcbddc->benign_B0));
1759c263805aSStefano Zampini       /* pop B0 from pcbddc->local_mat */
17609566063dSJacob Faibussowitsch       PetscCall(PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE));
1761c263805aSStefano Zampini     }
17625e8657edSStefano Zampini     /* get submatrices */
17639566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_IB));
17649566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_BI));
17659566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcis->A_BB));
17669566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB));
17679566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB));
17689566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI));
17693975b054SStefano Zampini     /* set flag in pcis to not reuse submatrices during PCISCreate */
17703975b054SStefano Zampini     pcis->reusesubmatrices = PETSC_FALSE;
17719c6a02ceSStefano Zampini   } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) {
17729566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&pcbddc->local_mat));
17739566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)matis->A));
17745e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
17755e8657edSStefano Zampini   }
177635509ce9Sstefano_zampini 
177735509ce9Sstefano_zampini   /* interface pressure block row for B_C */
17789566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP" ,(PetscObject*)&lP));
17799566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA));
178035509ce9Sstefano_zampini   if (lA && lP) {
178135509ce9Sstefano_zampini     PC_IS*    pcis = (PC_IS*)pc->data;
178235509ce9Sstefano_zampini     Mat       B_BI,B_BB,Bt_BI,Bt_BB;
178335509ce9Sstefano_zampini     PetscBool issym;
17849566063dSJacob Faibussowitsch     PetscCall(MatIsSymmetric(lA,PETSC_SMALL,&issym));
17856cc1294bSstefano_zampini     if (issym) {
17869566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI));
17879566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB));
17889566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(B_BI,&Bt_BI));
17899566063dSJacob Faibussowitsch       PetscCall(MatCreateTranspose(B_BB,&Bt_BB));
179035509ce9Sstefano_zampini     } else {
17919566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI));
17929566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB));
17939566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA,pcis->is_I_local,lP,MAT_INITIAL_MATRIX,&Bt_BI));
17949566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(lA,pcis->is_B_local,lP,MAT_INITIAL_MATRIX,&Bt_BB));
179535509ce9Sstefano_zampini     }
17969566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BI",(PetscObject)B_BI));
17979566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BB",(PetscObject)B_BB));
17989566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BI",(PetscObject)Bt_BI));
17999566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BB",(PetscObject)Bt_BB));
18009566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B_BI));
18019566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B_BB));
18029566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Bt_BI));
18039566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Bt_BB));
180435509ce9Sstefano_zampini   }
18059566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_LocalWork[pcbddc->current_level],pc,0,0,0));
180635509ce9Sstefano_zampini 
1807b96c3477SStefano Zampini   /* SetUp coarse and local Neumann solvers */
18089566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetUpSolvers(pc));
1809b96c3477SStefano Zampini   /* SetUp Scaling operator */
18109d54b7f4SStefano Zampini   if (pcbddc->use_deluxe_scaling) {
18119566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingSetUp(pc));
18120c7d97c5SJed Brown   }
1813c703fcc7SStefano Zampini 
18141dd7afcfSStefano Zampini   /* mark topography as done */
181556282151SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
18160369aaf7SStefano Zampini 
18171dd7afcfSStefano Zampini   /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */
18189566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignShellMat(pc,PETSC_FALSE));
18191dd7afcfSStefano Zampini 
182058a03d70SStefano Zampini   if (pcbddc->dbg_flag) {
18219566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2*pcbddc->current_level));
18229566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer));
18232b510759SStefano Zampini   }
18240c7d97c5SJed Brown   PetscFunctionReturn(0);
18250c7d97c5SJed Brown }
18260c7d97c5SJed Brown 
18270c7d97c5SJed Brown /*
182850efa1b5SStefano Zampini    PCApply_BDDC - Applies the BDDC operator to a vector.
18290c7d97c5SJed Brown 
18300c7d97c5SJed Brown    Input Parameters:
18310f202f7eSStefano Zampini +  pc - the preconditioner context
18320f202f7eSStefano Zampini -  r - input vector (global)
18330c7d97c5SJed Brown 
18340c7d97c5SJed Brown    Output Parameter:
18350c7d97c5SJed Brown .  z - output vector (global)
18360c7d97c5SJed Brown 
18370c7d97c5SJed Brown    Application Interface Routine: PCApply()
18380c7d97c5SJed Brown  */
183953cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
18400c7d97c5SJed Brown {
18410c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
18420c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1843b3338236SStefano Zampini   Mat               lA = NULL;
1844b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
18453b03a366Sstefano_zampini   const PetscScalar one = 1.0;
18463b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
18472617d88aSStefano Zampini   const PetscScalar zero = 0.0;
18480c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
18490c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
1850b097fa66SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */
18510c7d97c5SJed Brown 
18520c7d97c5SJed Brown   PetscFunctionBegin;
18539566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(citation,&cited));
1854b3338236SStefano Zampini   if (pcbddc->switch_static) {
18559566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat,&lA));
1856b3338236SStefano Zampini   }
1857b3338236SStefano Zampini 
18581dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
18591dd7afcfSStefano Zampini     Vec swap;
186027b6a85dSStefano Zampini 
18619566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change));
18621dd7afcfSStefano Zampini     swap = pcbddc->work_change;
18631dd7afcfSStefano Zampini     pcbddc->work_change = r;
18641dd7afcfSStefano Zampini     r = swap;
18651dd7afcfSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
18669cc2a9b1Sstefano_zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) {
18679566063dSJacob Faibussowitsch       PetscCall(VecCopy(r,pcis->vec1_global));
18689566063dSJacob Faibussowitsch       PetscCall(VecLockReadPush(pcis->vec1_global));
18691dd7afcfSStefano Zampini     }
18701dd7afcfSStefano Zampini   }
187127b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
18729566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE));
1873efc2fbd9SStefano Zampini   }
1874bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET && !pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
18759566063dSJacob Faibussowitsch     PetscCall(VecCopy(r,z));
18760c7d97c5SJed Brown     /* First Dirichlet solve */
18779566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
18789566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
18790c7d97c5SJed Brown     /*
18800c7d97c5SJed Brown       Assembling right hand side for BDDC operator
1881b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
1882674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
18830c7d97c5SJed Brown     */
1884b097fa66SStefano Zampini     if (n_D) {
18859566063dSJacob Faibussowitsch       PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
18869566063dSJacob Faibussowitsch       PetscCall(KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D));
18879566063dSJacob Faibussowitsch       PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
18889566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D));
18899566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec2_D,m_one));
189016909a7fSStefano Zampini       if (pcbddc->switch_static) {
18919566063dSJacob Faibussowitsch         PetscCall(VecSet(pcis->vec1_N,0.));
18929566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
18939566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
189416909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
18959566063dSJacob Faibussowitsch           PetscCall(MatMult(lA,pcis->vec1_N,pcis->vec2_N));
189616909a7fSStefano Zampini         } else {
18979566063dSJacob Faibussowitsch           PetscCall(MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N));
18989566063dSJacob Faibussowitsch           PetscCall(MatMult(lA,pcis->vec2_N,pcis->vec1_N));
18999566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N));
190016909a7fSStefano Zampini         }
19019566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD));
19029566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD));
19039566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
19049566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
190516909a7fSStefano Zampini       } else {
19069566063dSJacob Faibussowitsch         PetscCall(MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B));
190716909a7fSStefano Zampini       }
1908b097fa66SStefano Zampini     } else {
19099566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_B,zero));
1910b097fa66SStefano Zampini     }
19119566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE));
19129566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE));
19139566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingRestriction(pc,z,pcis->vec1_B));
1914b76ba322SStefano Zampini   } else {
19154fee134fSStefano Zampini     if (!pcbddc->benign_apply_coarse_only) {
19169566063dSJacob Faibussowitsch       PetscCall(PCBDDCScalingRestriction(pc,r,pcis->vec1_B));
1917b76ba322SStefano Zampini     }
19184fee134fSStefano Zampini   }
1919bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) {
192028b400f6SJacob Faibussowitsch     PetscCheck(pcbddc->switch_static,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"You forgot to pass -pc_bddc_switch_static");
19219566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
19229566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
1923bc960bbfSJed Brown   }
1924b76ba322SStefano Zampini 
19252617d88aSStefano Zampini   /* Apply interface preconditioner
19262617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
19279566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE));
19282617d88aSStefano Zampini 
1929674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
19309566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(pc,pcis->vec1_B,z));
1931bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) {
19329566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec1_D,z,INSERT_VALUES,SCATTER_REVERSE));
19339566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec1_D,z,INSERT_VALUES,SCATTER_REVERSE));
1934bc960bbfSJed Brown     PetscFunctionReturn(0);
1935bc960bbfSJed Brown   }
19363b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
19379566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
19389566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
1939b097fa66SStefano Zampini   if (n_B) {
194016909a7fSStefano Zampini     if (pcbddc->switch_static) {
19419566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
19429566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
19439566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
19449566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
194516909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
19469566063dSJacob Faibussowitsch         PetscCall(MatMult(lA,pcis->vec1_N,pcis->vec2_N));
194716909a7fSStefano Zampini       } else {
19489566063dSJacob Faibussowitsch         PetscCall(MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N));
19499566063dSJacob Faibussowitsch         PetscCall(MatMult(lA,pcis->vec2_N,pcis->vec1_N));
19509566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N));
195116909a7fSStefano Zampini       }
19529566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD));
19539566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD));
195416909a7fSStefano Zampini     } else {
19559566063dSJacob Faibussowitsch       PetscCall(MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D));
195616909a7fSStefano Zampini     }
195716909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
195816909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
19599566063dSJacob Faibussowitsch       PetscCall(MatMult(lA,pcis->vec1_D,pcis->vec3_D));
196016909a7fSStefano Zampini     } else {
19619566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N));
19629566063dSJacob Faibussowitsch       PetscCall(MatMult(lA,pcis->vec1_N,pcis->vec2_N));
19639566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D));
196416909a7fSStefano Zampini     }
1965b097fa66SStefano Zampini   }
19669566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
19679566063dSJacob Faibussowitsch   PetscCall(KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D));
19689566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
19699566063dSJacob Faibussowitsch   PetscCall(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec4_D));
1970efc2fbd9SStefano Zampini 
19718ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1972b097fa66SStefano Zampini     if (pcbddc->switch_static) {
19739566063dSJacob Faibussowitsch       PetscCall(VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D));
1974b097fa66SStefano Zampini     } else {
19759566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D));
1976b097fa66SStefano Zampini     }
19779566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE));
19789566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE));
1979b097fa66SStefano Zampini   } else {
1980b097fa66SStefano Zampini     if (pcbddc->switch_static) {
19819566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D));
1982b097fa66SStefano Zampini     } else {
19839566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec4_D,m_one));
1984b097fa66SStefano Zampini     }
19859566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE));
19869566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE));
1987b097fa66SStefano Zampini   }
198827b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
19891dd7afcfSStefano Zampini     if (pcbddc->benign_apply_coarse_only) {
19909566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n));
19911dd7afcfSStefano Zampini     }
19929566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE));
1993efc2fbd9SStefano Zampini   }
19941f4df5f7SStefano Zampini 
19951dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1996f913dca9SStefano Zampini     pcbddc->work_change = r;
19979566063dSJacob Faibussowitsch     PetscCall(VecCopy(z,pcbddc->work_change));
19989566063dSJacob Faibussowitsch     PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z));
19991dd7afcfSStefano Zampini   }
20000c7d97c5SJed Brown   PetscFunctionReturn(0);
20010c7d97c5SJed Brown }
200250efa1b5SStefano Zampini 
200350efa1b5SStefano Zampini /*
200450efa1b5SStefano Zampini    PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector.
200550efa1b5SStefano Zampini 
200650efa1b5SStefano Zampini    Input Parameters:
20070f202f7eSStefano Zampini +  pc - the preconditioner context
20080f202f7eSStefano Zampini -  r - input vector (global)
200950efa1b5SStefano Zampini 
201050efa1b5SStefano Zampini    Output Parameter:
201150efa1b5SStefano Zampini .  z - output vector (global)
201250efa1b5SStefano Zampini 
201350efa1b5SStefano Zampini    Application Interface Routine: PCApplyTranspose()
201450efa1b5SStefano Zampini  */
201550efa1b5SStefano Zampini PetscErrorCode PCApplyTranspose_BDDC(PC pc,Vec r,Vec z)
201650efa1b5SStefano Zampini {
201750efa1b5SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
201850efa1b5SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
2019b3338236SStefano Zampini   Mat               lA = NULL;
2020b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
202150efa1b5SStefano Zampini   const PetscScalar one = 1.0;
202250efa1b5SStefano Zampini   const PetscScalar m_one = -1.0;
202350efa1b5SStefano Zampini   const PetscScalar zero = 0.0;
202450efa1b5SStefano Zampini 
202550efa1b5SStefano Zampini   PetscFunctionBegin;
20269566063dSJacob Faibussowitsch   PetscCall(PetscCitationsRegister(citation,&cited));
2027b3338236SStefano Zampini   if (pcbddc->switch_static) {
20289566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat,&lA));
2029b3338236SStefano Zampini   }
20301dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
20311dd7afcfSStefano Zampini     Vec swap;
203227b6a85dSStefano Zampini 
20339566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change));
20341dd7afcfSStefano Zampini     swap = pcbddc->work_change;
20351dd7afcfSStefano Zampini     pcbddc->work_change = r;
20361dd7afcfSStefano Zampini     r = swap;
203727b6a85dSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
20388ae0ca82SStefano Zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->exact_dirichlet_trick_app && pcbddc->change_interior) {
20399566063dSJacob Faibussowitsch       PetscCall(VecCopy(r,pcis->vec1_global));
20409566063dSJacob Faibussowitsch       PetscCall(VecLockReadPush(pcis->vec1_global));
20411dd7afcfSStefano Zampini     }
204227b6a85dSStefano Zampini   }
204327b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
20449566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE));
2045537c1cdfSStefano Zampini   }
20468ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
20479566063dSJacob Faibussowitsch     PetscCall(VecCopy(r,z));
204850efa1b5SStefano Zampini     /* First Dirichlet solve */
20499566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
20509566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
205150efa1b5SStefano Zampini     /*
205250efa1b5SStefano Zampini       Assembling right hand side for BDDC operator
2053b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
205450efa1b5SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
205550efa1b5SStefano Zampini     */
2056b097fa66SStefano Zampini     if (n_D) {
20579566063dSJacob Faibussowitsch       PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
20589566063dSJacob Faibussowitsch       PetscCall(KSPSolveTranspose(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D));
20599566063dSJacob Faibussowitsch       PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
20609566063dSJacob Faibussowitsch       PetscCall(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D));
20619566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec2_D,m_one));
206216909a7fSStefano Zampini       if (pcbddc->switch_static) {
20639566063dSJacob Faibussowitsch         PetscCall(VecSet(pcis->vec1_N,0.));
20649566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
20659566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
206616909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
20679566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N));
206816909a7fSStefano Zampini         } else {
20699566063dSJacob Faibussowitsch           PetscCall(MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N));
20709566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(lA,pcis->vec2_N,pcis->vec1_N));
20719566063dSJacob Faibussowitsch           PetscCall(MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N));
207216909a7fSStefano Zampini         }
20739566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD));
20749566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD));
20759566063dSJacob Faibussowitsch         PetscCall(VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
20769566063dSJacob Faibussowitsch         PetscCall(VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
207716909a7fSStefano Zampini       } else {
20789566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcis->A_IB,pcis->vec2_D,pcis->vec1_B));
207916909a7fSStefano Zampini       }
2080b097fa66SStefano Zampini     } else {
20819566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->vec1_B,zero));
2082b097fa66SStefano Zampini     }
20839566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE));
20849566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE));
20859566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingRestriction(pc,z,pcis->vec1_B));
208650efa1b5SStefano Zampini   } else {
20879566063dSJacob Faibussowitsch     PetscCall(PCBDDCScalingRestriction(pc,r,pcis->vec1_B));
208850efa1b5SStefano Zampini   }
208950efa1b5SStefano Zampini 
209050efa1b5SStefano Zampini   /* Apply interface preconditioner
209150efa1b5SStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
20929566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(pc,PETSC_TRUE));
209350efa1b5SStefano Zampini 
209450efa1b5SStefano Zampini   /* Apply transpose of partition of unity operator */
20959566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(pc,pcis->vec1_B,z));
209650efa1b5SStefano Zampini 
209750efa1b5SStefano Zampini   /* Second Dirichlet solve and assembling of output */
20989566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
20999566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
2100b097fa66SStefano Zampini   if (n_B) {
210116909a7fSStefano Zampini     if (pcbddc->switch_static) {
21029566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
21039566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
21049566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
21059566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
210616909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
21079566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N));
210816909a7fSStefano Zampini       } else {
21099566063dSJacob Faibussowitsch         PetscCall(MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N));
21109566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(lA,pcis->vec2_N,pcis->vec1_N));
21119566063dSJacob Faibussowitsch         PetscCall(MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N));
211216909a7fSStefano Zampini       }
21139566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD));
21149566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD));
211516909a7fSStefano Zampini     } else {
21169566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcis->A_BI,pcis->vec1_B,pcis->vec3_D));
211716909a7fSStefano Zampini     }
211816909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
211916909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
21209566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(lA,pcis->vec1_D,pcis->vec3_D));
212116909a7fSStefano Zampini     } else {
21229566063dSJacob Faibussowitsch       PetscCall(MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N));
21239566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N));
21249566063dSJacob Faibussowitsch       PetscCall(MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D));
212516909a7fSStefano Zampini     }
2126b097fa66SStefano Zampini   }
21279566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
21289566063dSJacob Faibussowitsch   PetscCall(KSPSolveTranspose(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D));
21299566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
21309566063dSJacob Faibussowitsch   PetscCall(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec4_D));
21318ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
2132b097fa66SStefano Zampini     if (pcbddc->switch_static) {
21339566063dSJacob Faibussowitsch       PetscCall(VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D));
2134b097fa66SStefano Zampini     } else {
21359566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D));
2136b097fa66SStefano Zampini     }
21379566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE));
21389566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE));
2139b097fa66SStefano Zampini   } else {
2140b097fa66SStefano Zampini     if (pcbddc->switch_static) {
21419566063dSJacob Faibussowitsch       PetscCall(VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D));
2142b097fa66SStefano Zampini     } else {
21439566063dSJacob Faibussowitsch       PetscCall(VecScale(pcis->vec4_D,m_one));
2144b097fa66SStefano Zampini     }
21459566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE));
21469566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE));
2147b097fa66SStefano Zampini   }
214827b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
21499566063dSJacob Faibussowitsch     PetscCall(PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE));
2150537c1cdfSStefano Zampini   }
21511dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2152f913dca9SStefano Zampini     pcbddc->work_change = r;
21539566063dSJacob Faibussowitsch     PetscCall(VecCopy(z,pcbddc->work_change));
21549566063dSJacob Faibussowitsch     PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z));
21551dd7afcfSStefano Zampini   }
215650efa1b5SStefano Zampini   PetscFunctionReturn(0);
215750efa1b5SStefano Zampini }
2158674ae819SStefano Zampini 
21599326c5c6Sstefano_zampini PetscErrorCode PCReset_BDDC(PC pc)
2160da1bb401SStefano Zampini {
2161da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
21629326c5c6Sstefano_zampini   PC_IS          *pcis = (PC_IS*)pc->data;
21639326c5c6Sstefano_zampini   KSP            kspD,kspR,kspC;
2164da1bb401SStefano Zampini 
2165da1bb401SStefano Zampini   PetscFunctionBegin;
2166674ae819SStefano Zampini   /* free BDDC custom data  */
21679566063dSJacob Faibussowitsch   PetscCall(PCBDDCResetCustomization(pc));
2168674ae819SStefano Zampini   /* destroy objects related to topography */
21699566063dSJacob Faibussowitsch   PetscCall(PCBDDCResetTopography(pc));
217034a97f8cSStefano Zampini   /* destroy objects for scaling operator */
21719566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingDestroy(pc));
2172674ae819SStefano Zampini   /* free solvers stuff */
21739566063dSJacob Faibussowitsch   PetscCall(PCBDDCResetSolvers(pc));
217462a6ff1dSStefano Zampini   /* free global vectors needed in presolve */
21759566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->temp_solution));
21769566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcbddc->original_rhs));
21771dd7afcfSStefano Zampini   /* free data created by PCIS */
21789566063dSJacob Faibussowitsch   PetscCall(PCISDestroy(pc));
21799326c5c6Sstefano_zampini 
21809326c5c6Sstefano_zampini   /* restore defaults */
21819326c5c6Sstefano_zampini   kspD = pcbddc->ksp_D;
21829326c5c6Sstefano_zampini   kspR = pcbddc->ksp_R;
21839326c5c6Sstefano_zampini   kspC = pcbddc->coarse_ksp;
21849566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(pc->data,sizeof(*pcbddc)));
21859326c5c6Sstefano_zampini   pcis->n_neigh                     = -1;
21869326c5c6Sstefano_zampini   pcis->scaling_factor              = 1.0;
21879326c5c6Sstefano_zampini   pcis->reusesubmatrices            = PETSC_TRUE;
21889326c5c6Sstefano_zampini   pcbddc->use_local_adj             = PETSC_TRUE;
21899326c5c6Sstefano_zampini   pcbddc->use_vertices              = PETSC_TRUE;
21909326c5c6Sstefano_zampini   pcbddc->use_edges                 = PETSC_TRUE;
21919326c5c6Sstefano_zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
21929326c5c6Sstefano_zampini   pcbddc->vertex_size               = 1;
21939326c5c6Sstefano_zampini   pcbddc->recompute_topography      = PETSC_TRUE;
21949326c5c6Sstefano_zampini   pcbddc->coarse_size               = -1;
21959326c5c6Sstefano_zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
21969326c5c6Sstefano_zampini   pcbddc->coarsening_ratio          = 8;
21979326c5c6Sstefano_zampini   pcbddc->coarse_eqs_per_proc       = 1;
21989326c5c6Sstefano_zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
21999326c5c6Sstefano_zampini   pcbddc->nedfield                  = -1;
22009326c5c6Sstefano_zampini   pcbddc->nedglobal                 = PETSC_TRUE;
22019326c5c6Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
22029326c5c6Sstefano_zampini   pcbddc->sub_schurs_layers         = -1;
22039326c5c6Sstefano_zampini   pcbddc->ksp_D                     = kspD;
22049326c5c6Sstefano_zampini   pcbddc->ksp_R                     = kspR;
22059326c5c6Sstefano_zampini   pcbddc->coarse_ksp                = kspC;
22069326c5c6Sstefano_zampini   PetscFunctionReturn(0);
22079326c5c6Sstefano_zampini }
22089326c5c6Sstefano_zampini 
22099326c5c6Sstefano_zampini PetscErrorCode PCDestroy_BDDC(PC pc)
22109326c5c6Sstefano_zampini {
22119326c5c6Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
22129326c5c6Sstefano_zampini 
22139326c5c6Sstefano_zampini   PetscFunctionBegin;
22149566063dSJacob Faibussowitsch   PetscCall(PCReset_BDDC(pc));
22159566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcbddc->ksp_D));
22169566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcbddc->ksp_R));
22179566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcbddc->coarse_ksp));
22189566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",NULL));
22199566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",NULL));
22209566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",NULL));
22219566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL));
22229566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",NULL));
22239566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL));
22249566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL));
22259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL));
22269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL));
22279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL));
22289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",NULL));
22299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL));
22309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",NULL));
22319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL));
22329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",NULL));
22339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL));
22349566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",NULL));
22359566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL));
22369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",NULL));
22379566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL));
22389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL));
22399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL));
22409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL));
22419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",NULL));
22429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",NULL));
22439566063dSJacob Faibussowitsch   PetscCall(PetscFree(pc->data));
2244da1bb401SStefano Zampini   PetscFunctionReturn(0);
2245da1bb401SStefano Zampini }
22461e6b0712SBarry Smith 
2247ab8c8b98SStefano Zampini static PetscErrorCode PCSetCoordinates_BDDC(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
2248ab8c8b98SStefano Zampini {
2249ab8c8b98SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2250ab8c8b98SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
2251ab8c8b98SStefano Zampini 
2252ab8c8b98SStefano Zampini   PetscFunctionBegin;
22539566063dSJacob Faibussowitsch   PetscCall(PetscFree(mat_graph->coords));
22549566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nloc*dim,&mat_graph->coords));
22559566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(mat_graph->coords,coords,nloc*dim));
2256ab8c8b98SStefano Zampini   mat_graph->cnloc = nloc;
2257ab8c8b98SStefano Zampini   mat_graph->cdim  = dim;
2258ab8c8b98SStefano Zampini   mat_graph->cloc  = PETSC_FALSE;
22594f819b78SStefano Zampini   /* flg setup */
22604f819b78SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
22614f819b78SStefano Zampini   pcbddc->corner_selected = PETSC_FALSE;
2262ab8c8b98SStefano Zampini   PetscFunctionReturn(0);
2263ab8c8b98SStefano Zampini }
2264ab8c8b98SStefano Zampini 
2265a06fd7f2SStefano Zampini static PetscErrorCode PCPreSolveChangeRHS_BDDC(PC pc, PetscBool* change)
2266a06fd7f2SStefano Zampini {
2267a06fd7f2SStefano Zampini   PetscFunctionBegin;
2268a06fd7f2SStefano Zampini   *change = PETSC_TRUE;
2269a06fd7f2SStefano Zampini   PetscFunctionReturn(0);
2270a06fd7f2SStefano Zampini }
2271a06fd7f2SStefano Zampini 
22723425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
22733425bc38SStefano Zampini {
2274674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
2275266e20e9SStefano Zampini   Vec            work;
22763425bc38SStefano Zampini   PC_IS*         pcis;
22773425bc38SStefano Zampini   PC_BDDC*       pcbddc;
22780c7d97c5SJed Brown 
22793425bc38SStefano Zampini   PetscFunctionBegin;
22809566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat,&mat_ctx));
22813425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
22823425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
22833425bc38SStefano Zampini 
22849566063dSJacob Faibussowitsch   PetscCall(VecSet(fetidp_flux_rhs,0.0));
2285229984c5Sstefano_zampini   /* copy rhs since we may change it during PCPreSolve_BDDC */
2286229984c5Sstefano_zampini   if (!pcbddc->original_rhs) {
22879566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs));
2288229984c5Sstefano_zampini   }
22896cc1294bSstefano_zampini   if (mat_ctx->rhs_flip) {
22909566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(pcbddc->original_rhs,standard_rhs,mat_ctx->rhs_flip));
22916cc1294bSstefano_zampini   } else {
22929566063dSJacob Faibussowitsch     PetscCall(VecCopy(standard_rhs,pcbddc->original_rhs));
22936cc1294bSstefano_zampini   }
2294af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
2295229984c5Sstefano_zampini     /* interface pressure rhs */
22969566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE));
22979566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE));
22989566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD));
22999566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD));
23006cc1294bSstefano_zampini     if (!mat_ctx->rhs_flip) {
23019566063dSJacob Faibussowitsch       PetscCall(VecScale(fetidp_flux_rhs,-1.));
2302229984c5Sstefano_zampini     }
23036cc1294bSstefano_zampini   }
2304c08af4c6SStefano Zampini   /*
2305c08af4c6SStefano Zampini      change of basis for physical rhs if needed
2306c08af4c6SStefano Zampini      It also changes the rhs in case of dirichlet boundaries
2307c08af4c6SStefano Zampini   */
23089566063dSJacob Faibussowitsch   PetscCall(PCPreSolve_BDDC(mat_ctx->pc,NULL,pcbddc->original_rhs,NULL));
2309fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
23109566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcbddc->original_rhs,pcbddc->work_change));
23113738a8e6SStefano Zampini     work = pcbddc->work_change;
2312fc17d649SStefano Zampini    } else {
23133738a8e6SStefano Zampini     work = pcbddc->original_rhs;
2314fc17d649SStefano Zampini   }
23153425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
23169566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD));
23179566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD));
2318fb223d50SStefano Zampini   /* scale rhs since it should be unassembled */
2319fb223d50SStefano Zampini   /* TODO use counter scaling? (also below) */
23209566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD));
23219566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD));
2322674ae819SStefano Zampini   /* Apply partition of unity */
23239566063dSJacob Faibussowitsch   PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B));
23249566063dSJacob Faibussowitsch   /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */
23258eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
23263425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
23279566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0));
23289566063dSJacob Faibussowitsch     PetscCall(KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D));
23299566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0));
2330c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
23319566063dSJacob Faibussowitsch     PetscCall(MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B));
23329566063dSJacob Faibussowitsch     PetscCall(VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B));
23339566063dSJacob Faibussowitsch     PetscCall(VecSet(work,0.0));
23349566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE));
23359566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE));
23369566063dSJacob Faibussowitsch     /* PetscCall(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */
23379566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD));
23389566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD));
23399566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B));
23403425bc38SStefano Zampini   }
23413425bc38SStefano Zampini   /* BDDC rhs */
23429566063dSJacob Faibussowitsch   PetscCall(VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B));
23438eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
23449566063dSJacob Faibussowitsch     PetscCall(VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D));
23453425bc38SStefano Zampini   }
23463425bc38SStefano Zampini   /* apply BDDC */
23479566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n));
23489566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE));
23499566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n));
2350229984c5Sstefano_zampini 
23513425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
23529566063dSJacob Faibussowitsch   PetscCall(MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local));
23539566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD));
23549566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD));
2355229984c5Sstefano_zampini   /* Add contribution to interface pressures */
2356229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
23579566063dSJacob Faibussowitsch     PetscCall(MatMult(mat_ctx->B_BB,pcis->vec1_B,mat_ctx->vP));
2358229984c5Sstefano_zampini     if (pcbddc->switch_static) {
23599566063dSJacob Faibussowitsch       PetscCall(MatMultAdd(mat_ctx->B_BI,pcis->vec1_D,mat_ctx->vP,mat_ctx->vP));
2360229984c5Sstefano_zampini     }
23619566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD));
23629566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD));
2363229984c5Sstefano_zampini   }
23643425bc38SStefano Zampini   PetscFunctionReturn(0);
23653425bc38SStefano Zampini }
23661e6b0712SBarry Smith 
23673425bc38SStefano Zampini /*@
23680f202f7eSStefano Zampini  PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side
23693425bc38SStefano Zampini 
23703425bc38SStefano Zampini    Collective
23713425bc38SStefano Zampini 
23723425bc38SStefano Zampini    Input Parameters:
23730f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix object obtained by a call to PCBDDCCreateFETIDPOperators
23740f202f7eSStefano Zampini -  standard_rhs    - the right-hand side of the original linear system
23753425bc38SStefano Zampini 
23763425bc38SStefano Zampini    Output Parameters:
23770f202f7eSStefano Zampini .  fetidp_flux_rhs - the right-hand side for the FETI-DP linear system
23783425bc38SStefano Zampini 
23793425bc38SStefano Zampini    Level: developer
23803425bc38SStefano Zampini 
23813425bc38SStefano Zampini    Notes:
23823425bc38SStefano Zampini 
238316b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCCreateFETIDPOperators()`, `PCBDDCMatFETIDPGetSolution()`
23843425bc38SStefano Zampini @*/
23853425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
23863425bc38SStefano Zampini {
2387674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
23883425bc38SStefano Zampini 
23893425bc38SStefano Zampini   PetscFunctionBegin;
2390266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1);
2391266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_rhs,VEC_CLASSID,2);
2392266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_rhs,VEC_CLASSID,3);
23939566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat,&mat_ctx));
2394cac4c232SBarry Smith   PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));
23953425bc38SStefano Zampini   PetscFunctionReturn(0);
23963425bc38SStefano Zampini }
23971e6b0712SBarry Smith 
23983425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
23993425bc38SStefano Zampini {
2400674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
24013425bc38SStefano Zampini   PC_IS*         pcis;
24023425bc38SStefano Zampini   PC_BDDC*       pcbddc;
2403229984c5Sstefano_zampini   Vec            work;
24043425bc38SStefano Zampini 
24053425bc38SStefano Zampini   PetscFunctionBegin;
24069566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat,&mat_ctx));
24073425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
24083425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
24093425bc38SStefano Zampini 
24103425bc38SStefano Zampini   /* apply B_delta^T */
24119566063dSJacob Faibussowitsch   PetscCall(VecSet(pcis->vec1_B,0.));
24129566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE));
24139566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE));
24149566063dSJacob Faibussowitsch   PetscCall(MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B));
2415229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
24169566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE));
24179566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE));
24189566063dSJacob Faibussowitsch     PetscCall(MatMultAdd(mat_ctx->Bt_BB,mat_ctx->vP,pcis->vec1_B,pcis->vec1_B));
2419229984c5Sstefano_zampini   }
2420229984c5Sstefano_zampini 
24213425bc38SStefano Zampini   /* compute rhs for BDDC application */
24229566063dSJacob Faibussowitsch   PetscCall(VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B));
24238eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
24249566063dSJacob Faibussowitsch     PetscCall(VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D));
2425229984c5Sstefano_zampini     if (mat_ctx->l2g_p) {
24269566063dSJacob Faibussowitsch       PetscCall(VecScale(mat_ctx->vP,-1.));
24279566063dSJacob Faibussowitsch       PetscCall(MatMultAdd(mat_ctx->Bt_BI,mat_ctx->vP,pcis->vec1_D,pcis->vec1_D));
24283425bc38SStefano Zampini     }
2429229984c5Sstefano_zampini   }
2430229984c5Sstefano_zampini 
24313425bc38SStefano Zampini   /* apply BDDC */
24329566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n));
24339566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE));
2434229984c5Sstefano_zampini 
2435229984c5Sstefano_zampini   /* put values into global vector */
2436af140850Sstefano_zampini   if (pcbddc->ChangeOfBasisMatrix) work = pcbddc->work_change;
2437af140850Sstefano_zampini   else work = standard_sol;
24389566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE));
24399566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE));
24408eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
24413425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
24429566063dSJacob Faibussowitsch     PetscCall(MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D));
24439566063dSJacob Faibussowitsch     PetscCall(VecAYPX(pcis->vec1_D,-1.0,mat_ctx->temp_solution_D));
24449566063dSJacob Faibussowitsch     PetscCall(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0));
24459566063dSJacob Faibussowitsch     PetscCall(KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec1_D));
24469566063dSJacob Faibussowitsch     PetscCall(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0));
2447c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
24483425bc38SStefano Zampini   }
2449229984c5Sstefano_zampini 
24509566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE));
24519566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE));
2452266e20e9SStefano Zampini   /* add p0 solution to final solution */
24539566063dSJacob Faibussowitsch   PetscCall(PCBDDCBenignGetOrSetP0(mat_ctx->pc,work,PETSC_FALSE));
2454fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
24559566063dSJacob Faibussowitsch     PetscCall(MatMult(pcbddc->ChangeOfBasisMatrix,work,standard_sol));
2456fc17d649SStefano Zampini   }
24579566063dSJacob Faibussowitsch   PetscCall(PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol));
2458af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
24599566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE));
24609566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE));
2461229984c5Sstefano_zampini   }
24623425bc38SStefano Zampini   PetscFunctionReturn(0);
24633425bc38SStefano Zampini }
24641e6b0712SBarry Smith 
24655a1e936bSStefano Zampini static PetscErrorCode PCView_BDDCIPC(PC pc, PetscViewer viewer)
24665a1e936bSStefano Zampini {
24675a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
24685a1e936bSStefano Zampini   PetscBool      isascii;
24695a1e936bSStefano Zampini 
24705a1e936bSStefano Zampini   PetscFunctionBegin;
24719566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc,&bddcipc_ctx));
24729566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
24735a1e936bSStefano Zampini   if (isascii) {
24749566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"BDDC interface preconditioner\n"));
24755a1e936bSStefano Zampini   }
24769566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPushTab(viewer));
24779566063dSJacob Faibussowitsch   PetscCall(PCView(bddcipc_ctx->bddc,viewer));
24789566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPopTab(viewer));
24795a1e936bSStefano Zampini   PetscFunctionReturn(0);
24805a1e936bSStefano Zampini }
24815a1e936bSStefano Zampini 
24825a1e936bSStefano Zampini static PetscErrorCode PCSetUp_BDDCIPC(PC pc)
24835a1e936bSStefano Zampini {
24845a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
24855a1e936bSStefano Zampini   PetscBool      isbddc;
24865a1e936bSStefano Zampini   Vec            vv;
24875a1e936bSStefano Zampini   IS             is;
24885a1e936bSStefano Zampini   PC_IS          *pcis;
24895a1e936bSStefano Zampini 
24905a1e936bSStefano Zampini   PetscFunctionBegin;
24919566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc,&bddcipc_ctx));
24929566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)bddcipc_ctx->bddc,PCBDDC,&isbddc));
249328b400f6SJacob Faibussowitsch   PetscCheck(isbddc,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid type %s. Must be of type bddc",((PetscObject)bddcipc_ctx->bddc)->type_name);
24949566063dSJacob Faibussowitsch   PetscCall(PCSetUp(bddcipc_ctx->bddc));
24955a1e936bSStefano Zampini 
24965a1e936bSStefano Zampini   /* create interface scatter */
24975a1e936bSStefano Zampini   pcis = (PC_IS*)(bddcipc_ctx->bddc->data);
24989566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l));
24999566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(pc->pmat,&vv,NULL));
25009566063dSJacob Faibussowitsch   PetscCall(ISRenumber(pcis->is_B_global,NULL,NULL,&is));
25019566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(vv,is,pcis->vec1_B,NULL,&bddcipc_ctx->g2l));
25029566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
25039566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&vv));
25045a1e936bSStefano Zampini   PetscFunctionReturn(0);
25055a1e936bSStefano Zampini }
25065a1e936bSStefano Zampini 
25075a1e936bSStefano Zampini static PetscErrorCode PCApply_BDDCIPC(PC pc, Vec r, Vec x)
25085a1e936bSStefano Zampini {
25095a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25105a1e936bSStefano Zampini   PC_IS          *pcis;
25115a1e936bSStefano Zampini   VecScatter     tmps;
25125a1e936bSStefano Zampini 
25135a1e936bSStefano Zampini   PetscFunctionBegin;
25149566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc,&bddcipc_ctx));
25155a1e936bSStefano Zampini   pcis = (PC_IS*)(bddcipc_ctx->bddc->data);
25165a1e936bSStefano Zampini   tmps = pcis->global_to_B;
25175a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
25189566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc,r,pcis->vec1_B));
25199566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc,PETSC_FALSE));
25209566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc,pcis->vec1_B,x));
25215a1e936bSStefano Zampini   pcis->global_to_B = tmps;
25225a1e936bSStefano Zampini   PetscFunctionReturn(0);
25235a1e936bSStefano Zampini }
25245a1e936bSStefano Zampini 
25255a1e936bSStefano Zampini static PetscErrorCode PCApplyTranspose_BDDCIPC(PC pc, Vec r, Vec x)
25265a1e936bSStefano Zampini {
25275a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25285a1e936bSStefano Zampini   PC_IS          *pcis;
25295a1e936bSStefano Zampini   VecScatter     tmps;
25305a1e936bSStefano Zampini 
25315a1e936bSStefano Zampini   PetscFunctionBegin;
25329566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc,&bddcipc_ctx));
25335a1e936bSStefano Zampini   pcis = (PC_IS*)(bddcipc_ctx->bddc->data);
25345a1e936bSStefano Zampini   tmps = pcis->global_to_B;
25355a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
25369566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingRestriction(bddcipc_ctx->bddc,r,pcis->vec1_B));
25379566063dSJacob Faibussowitsch   PetscCall(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc,PETSC_TRUE));
25389566063dSJacob Faibussowitsch   PetscCall(PCBDDCScalingExtension(bddcipc_ctx->bddc,pcis->vec1_B,x));
25395a1e936bSStefano Zampini   pcis->global_to_B = tmps;
25405a1e936bSStefano Zampini   PetscFunctionReturn(0);
25415a1e936bSStefano Zampini }
25425a1e936bSStefano Zampini 
25435a1e936bSStefano Zampini static PetscErrorCode PCDestroy_BDDCIPC(PC pc)
25445a1e936bSStefano Zampini {
25455a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25465a1e936bSStefano Zampini 
25475a1e936bSStefano Zampini   PetscFunctionBegin;
25489566063dSJacob Faibussowitsch   PetscCall(PCShellGetContext(pc,&bddcipc_ctx));
25499566063dSJacob Faibussowitsch   PetscCall(PCDestroy(&bddcipc_ctx->bddc));
25509566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&bddcipc_ctx->g2l));
25519566063dSJacob Faibussowitsch   PetscCall(PetscFree(bddcipc_ctx));
25525a1e936bSStefano Zampini   PetscFunctionReturn(0);
25535a1e936bSStefano Zampini }
25545a1e936bSStefano Zampini 
25553425bc38SStefano Zampini /*@
25560f202f7eSStefano Zampini  PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system
25573425bc38SStefano Zampini 
25583425bc38SStefano Zampini    Collective
25593425bc38SStefano Zampini 
25603425bc38SStefano Zampini    Input Parameters:
25610f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators
25620f202f7eSStefano Zampini -  fetidp_flux_sol - the solution of the FETI-DP linear system
25633425bc38SStefano Zampini 
25643425bc38SStefano Zampini    Output Parameters:
25650f202f7eSStefano Zampini .  standard_sol    - the solution defined on the physical domain
25663425bc38SStefano Zampini 
25673425bc38SStefano Zampini    Level: developer
25683425bc38SStefano Zampini 
25693425bc38SStefano Zampini    Notes:
25703425bc38SStefano Zampini 
257116b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCCreateFETIDPOperators()`, `PCBDDCMatFETIDPGetRHS()`
25723425bc38SStefano Zampini @*/
25733425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
25743425bc38SStefano Zampini {
2575674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
25763425bc38SStefano Zampini 
25773425bc38SStefano Zampini   PetscFunctionBegin;
2578266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1);
2579266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_sol,VEC_CLASSID,2);
2580266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_sol,VEC_CLASSID,3);
25819566063dSJacob Faibussowitsch   PetscCall(MatShellGetContext(fetidp_mat,&mat_ctx));
2582cac4c232SBarry Smith   PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));
25833425bc38SStefano Zampini   PetscFunctionReturn(0);
25843425bc38SStefano Zampini }
25851e6b0712SBarry Smith 
2586547c9a8eSstefano_zampini static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, PetscBool fully_redundant, const char* prefix, Mat *fetidp_mat, PC *fetidp_pc)
25873425bc38SStefano Zampini {
2588674ae819SStefano Zampini 
2589674ae819SStefano Zampini   FETIDPMat_ctx  fetidpmat_ctx;
25903425bc38SStefano Zampini   Mat            newmat;
2591674ae819SStefano Zampini   FETIDPPC_ctx   fetidppc_ctx;
25923425bc38SStefano Zampini   PC             newpc;
2593ce94432eSBarry Smith   MPI_Comm       comm;
25943425bc38SStefano Zampini 
25953425bc38SStefano Zampini   PetscFunctionBegin;
25969566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)pc,&comm));
259715579a77SStefano Zampini   /* FETI-DP matrix */
25989566063dSJacob Faibussowitsch   PetscCall(PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx));
25991720468bSStefano Zampini   fetidpmat_ctx->fully_redundant = fully_redundant;
26009566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetupFETIDPMatContext(fetidpmat_ctx));
26019566063dSJacob Faibussowitsch   PetscCall(MatCreateShell(comm,fetidpmat_ctx->n,fetidpmat_ctx->n,fetidpmat_ctx->N,fetidpmat_ctx->N,fetidpmat_ctx,&newmat));
26029566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)newmat,!fetidpmat_ctx->l2g_lambda_only ? "F" : "G"));
26039566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult));
26049566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(newmat,MATOP_MULT_TRANSPOSE,(void (*)(void))FETIDPMatMultTranspose));
26059566063dSJacob Faibussowitsch   PetscCall(MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat));
260615579a77SStefano Zampini   /* propagate MatOptions */
260715579a77SStefano Zampini   {
260815579a77SStefano Zampini     PC_BDDC   *pcbddc = (PC_BDDC*)fetidpmat_ctx->pc->data;
260915579a77SStefano Zampini     PetscBool issym;
261015579a77SStefano Zampini 
26119566063dSJacob Faibussowitsch     PetscCall(MatGetOption(pc->mat,MAT_SYMMETRIC,&issym));
261215579a77SStefano Zampini     if (issym || pcbddc->symmetric_primal) {
26139566063dSJacob Faibussowitsch       PetscCall(MatSetOption(newmat,MAT_SYMMETRIC,PETSC_TRUE));
261415579a77SStefano Zampini     }
261515579a77SStefano Zampini   }
26169566063dSJacob Faibussowitsch   PetscCall(MatSetOptionsPrefix(newmat,prefix));
26179566063dSJacob Faibussowitsch   PetscCall(MatAppendOptionsPrefix(newmat,"fetidp_"));
26189566063dSJacob Faibussowitsch   PetscCall(MatSetUp(newmat));
261915579a77SStefano Zampini   /* FETI-DP preconditioner */
26209566063dSJacob Faibussowitsch   PetscCall(PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx));
26219566063dSJacob Faibussowitsch   PetscCall(PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx));
26229566063dSJacob Faibussowitsch   PetscCall(PCCreate(comm,&newpc));
26239566063dSJacob Faibussowitsch   PetscCall(PCSetOperators(newpc,newmat,newmat));
26249566063dSJacob Faibussowitsch   PetscCall(PCSetOptionsPrefix(newpc,prefix));
26259566063dSJacob Faibussowitsch   PetscCall(PCAppendOptionsPrefix(newpc,"fetidp_"));
26269566063dSJacob Faibussowitsch   PetscCall(PCSetErrorIfFailure(newpc,pc->erroriffailure));
262715579a77SStefano Zampini   if (!fetidpmat_ctx->l2g_lambda_only) { /* standard FETI-DP */
26289566063dSJacob Faibussowitsch     PetscCall(PCSetType(newpc,PCSHELL));
26299566063dSJacob Faibussowitsch     PetscCall(PCShellSetName(newpc,"FETI-DP multipliers"));
26309566063dSJacob Faibussowitsch     PetscCall(PCShellSetContext(newpc,fetidppc_ctx));
26319566063dSJacob Faibussowitsch     PetscCall(PCShellSetApply(newpc,FETIDPPCApply));
26329566063dSJacob Faibussowitsch     PetscCall(PCShellSetApplyTranspose(newpc,FETIDPPCApplyTranspose));
26339566063dSJacob Faibussowitsch     PetscCall(PCShellSetView(newpc,FETIDPPCView));
26349566063dSJacob Faibussowitsch     PetscCall(PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC));
26355a1e936bSStefano Zampini   } else { /* saddle-point FETI-DP */
26365a1e936bSStefano Zampini     Mat       M;
26375a1e936bSStefano Zampini     PetscInt  psize;
26385a1e936bSStefano Zampini     PetscBool fake = PETSC_FALSE, isfieldsplit;
2639e1214c54Sstefano_zampini 
26409566063dSJacob Faibussowitsch     PetscCall(ISViewFromOptions(fetidpmat_ctx->lagrange,NULL,"-lag_view"));
26419566063dSJacob Faibussowitsch     PetscCall(ISViewFromOptions(fetidpmat_ctx->pressure,NULL,"-press_view"));
26429566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_PPmat",(PetscObject*)&M));
26439566063dSJacob Faibussowitsch     PetscCall(PCSetType(newpc,PCFIELDSPLIT));
26449566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetIS(newpc,"lag",fetidpmat_ctx->lagrange));
26459566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetIS(newpc,"p",fetidpmat_ctx->pressure));
26469566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetType(newpc,PC_COMPOSITE_SCHUR));
26479566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetSchurFactType(newpc,PC_FIELDSPLIT_SCHUR_FACT_DIAG));
26489566063dSJacob Faibussowitsch     PetscCall(ISGetSize(fetidpmat_ctx->pressure,&psize));
26495a1e936bSStefano Zampini     if (psize != M->rmap->N) {
26505a1e936bSStefano Zampini       Mat      M2;
26515a1e936bSStefano Zampini       PetscInt lpsize;
26525a1e936bSStefano Zampini 
26535a1e936bSStefano Zampini       fake = PETSC_TRUE;
26549566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(fetidpmat_ctx->pressure,&lpsize));
26559566063dSJacob Faibussowitsch       PetscCall(MatCreate(comm,&M2));
26569566063dSJacob Faibussowitsch       PetscCall(MatSetType(M2,MATAIJ));
26579566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(M2,lpsize,lpsize,psize,psize));
26589566063dSJacob Faibussowitsch       PetscCall(MatSetUp(M2));
26599566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(M2,MAT_FINAL_ASSEMBLY));
26609566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(M2,MAT_FINAL_ASSEMBLY));
26619566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSetSchurPre(newpc,PC_FIELDSPLIT_SCHUR_PRE_USER,M2));
26629566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&M2));
26635a1e936bSStefano Zampini     } else {
26649566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSetSchurPre(newpc,PC_FIELDSPLIT_SCHUR_PRE_USER,M));
26655a1e936bSStefano Zampini     }
26669566063dSJacob Faibussowitsch     PetscCall(PCFieldSplitSetSchurScale(newpc,1.0));
266715579a77SStefano Zampini 
266815579a77SStefano Zampini     /* we need to setfromoptions and setup here to access the blocks */
26699566063dSJacob Faibussowitsch     PetscCall(PCSetFromOptions(newpc));
26709566063dSJacob Faibussowitsch     PetscCall(PCSetUp(newpc));
2671e1214c54Sstefano_zampini 
26725a1e936bSStefano Zampini     /* user may have changed the type (e.g. -fetidp_pc_type none) */
26739566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)newpc,PCFIELDSPLIT,&isfieldsplit));
26745a1e936bSStefano Zampini     if (isfieldsplit) {
26755a1e936bSStefano Zampini       KSP       *ksps;
26765a1e936bSStefano Zampini       PC        ppc,lagpc;
26775a1e936bSStefano Zampini       PetscInt  nn;
2678064a4176SStefano Zampini       PetscBool ismatis,matisok = PETSC_FALSE,check = PETSC_FALSE;
26795a1e936bSStefano Zampini 
2680e1214c54Sstefano_zampini       /* set the solver for the (0,0) block */
26819566063dSJacob Faibussowitsch       PetscCall(PCFieldSplitSchurGetSubKSP(newpc,&nn,&ksps));
26825a1e936bSStefano Zampini       if (!nn) { /* not of type PC_COMPOSITE_SCHUR */
26839566063dSJacob Faibussowitsch         PetscCall(PCFieldSplitGetSubKSP(newpc,&nn,&ksps));
26845a1e936bSStefano Zampini         if (!fake) { /* pass pmat to the pressure solver */
26855a1e936bSStefano Zampini           Mat F;
26865a1e936bSStefano Zampini 
26879566063dSJacob Faibussowitsch           PetscCall(KSPGetOperators(ksps[1],&F,NULL));
26889566063dSJacob Faibussowitsch           PetscCall(KSPSetOperators(ksps[1],F,M));
26895a1e936bSStefano Zampini         }
26905a1e936bSStefano Zampini       } else {
26915a1e936bSStefano Zampini         PetscBool issym;
26925a1e936bSStefano Zampini         Mat       S;
26935a1e936bSStefano Zampini 
26949566063dSJacob Faibussowitsch         PetscCall(PCFieldSplitSchurGetS(newpc,&S));
26955a1e936bSStefano Zampini 
26969566063dSJacob Faibussowitsch         PetscCall(MatGetOption(newmat,MAT_SYMMETRIC,&issym));
26975a1e936bSStefano Zampini         if (issym) {
26989566063dSJacob Faibussowitsch           PetscCall(MatSetOption(S,MAT_SYMMETRIC,PETSC_TRUE));
26995a1e936bSStefano Zampini         }
27005a1e936bSStefano Zampini       }
27019566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksps[0],&lagpc));
27029566063dSJacob Faibussowitsch       PetscCall(PCSetType(lagpc,PCSHELL));
27039566063dSJacob Faibussowitsch       PetscCall(PCShellSetName(lagpc,"FETI-DP multipliers"));
27049566063dSJacob Faibussowitsch       PetscCall(PCShellSetContext(lagpc,fetidppc_ctx));
27059566063dSJacob Faibussowitsch       PetscCall(PCShellSetApply(lagpc,FETIDPPCApply));
27069566063dSJacob Faibussowitsch       PetscCall(PCShellSetApplyTranspose(lagpc,FETIDPPCApplyTranspose));
27079566063dSJacob Faibussowitsch       PetscCall(PCShellSetView(lagpc,FETIDPPCView));
27089566063dSJacob Faibussowitsch       PetscCall(PCShellSetDestroy(lagpc,PCBDDCDestroyFETIDPPC));
27095a1e936bSStefano Zampini 
27105a1e936bSStefano Zampini       /* Olof's idea: interface Schur complement preconditioner for the mass matrix */
27119566063dSJacob Faibussowitsch       PetscCall(KSPGetPC(ksps[1],&ppc));
27125a1e936bSStefano Zampini       if (fake) {
27135a1e936bSStefano Zampini         BDDCIPC_ctx    bddcipc_ctx;
2714ff11fd76SStefano Zampini         PetscContainer c;
27155a1e936bSStefano Zampini 
27165a1e936bSStefano Zampini         matisok = PETSC_TRUE;
27175a1e936bSStefano Zampini 
27185a1e936bSStefano Zampini         /* create inner BDDC solver */
27199566063dSJacob Faibussowitsch         PetscCall(PetscNew(&bddcipc_ctx));
27209566063dSJacob Faibussowitsch         PetscCall(PCCreate(comm,&bddcipc_ctx->bddc));
27219566063dSJacob Faibussowitsch         PetscCall(PCSetType(bddcipc_ctx->bddc,PCBDDC));
27229566063dSJacob Faibussowitsch         PetscCall(PCSetOperators(bddcipc_ctx->bddc,M,M));
27239566063dSJacob Faibussowitsch         PetscCall(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_pCSR",(PetscObject*)&c));
27249566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)M,MATIS,&ismatis));
2725ff11fd76SStefano Zampini         if (c && ismatis) {
2726ff11fd76SStefano Zampini           Mat      lM;
2727ff11fd76SStefano Zampini           PetscInt *csr,n;
2728ff11fd76SStefano Zampini 
27299566063dSJacob Faibussowitsch           PetscCall(MatISGetLocalMat(M,&lM));
27309566063dSJacob Faibussowitsch           PetscCall(MatGetSize(lM,&n,NULL));
27319566063dSJacob Faibussowitsch           PetscCall(PetscContainerGetPointer(c,(void**)&csr));
27329566063dSJacob Faibussowitsch           PetscCall(PCBDDCSetLocalAdjacencyGraph(bddcipc_ctx->bddc,n,csr,csr + (n + 1),PETSC_COPY_VALUES));
27339566063dSJacob Faibussowitsch           PetscCall(MatISRestoreLocalMat(M,&lM));
2734ff11fd76SStefano Zampini         }
27359566063dSJacob Faibussowitsch         PetscCall(PCSetOptionsPrefix(bddcipc_ctx->bddc,((PetscObject)ksps[1])->prefix));
27369566063dSJacob Faibussowitsch         PetscCall(PCSetErrorIfFailure(bddcipc_ctx->bddc,pc->erroriffailure));
27379566063dSJacob Faibussowitsch         PetscCall(PCSetFromOptions(bddcipc_ctx->bddc));
27385a1e936bSStefano Zampini 
27395a1e936bSStefano Zampini         /* wrap the interface application */
27409566063dSJacob Faibussowitsch         PetscCall(PCSetType(ppc,PCSHELL));
27419566063dSJacob Faibussowitsch         PetscCall(PCShellSetName(ppc,"FETI-DP pressure"));
27429566063dSJacob Faibussowitsch         PetscCall(PCShellSetContext(ppc,bddcipc_ctx));
27439566063dSJacob Faibussowitsch         PetscCall(PCShellSetSetUp(ppc,PCSetUp_BDDCIPC));
27449566063dSJacob Faibussowitsch         PetscCall(PCShellSetApply(ppc,PCApply_BDDCIPC));
27459566063dSJacob Faibussowitsch         PetscCall(PCShellSetApplyTranspose(ppc,PCApplyTranspose_BDDCIPC));
27469566063dSJacob Faibussowitsch         PetscCall(PCShellSetView(ppc,PCView_BDDCIPC));
27479566063dSJacob Faibussowitsch         PetscCall(PCShellSetDestroy(ppc,PCDestroy_BDDCIPC));
27485a1e936bSStefano Zampini       }
27495a1e936bSStefano Zampini 
27505a1e936bSStefano Zampini       /* determine if we need to assemble M to construct a preconditioner */
27515a1e936bSStefano Zampini       if (!matisok) {
27529566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)M,MATIS,&ismatis));
27539566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompareAny((PetscObject)ppc,&matisok,PCBDDC,PCJACOBI,PCNONE,PCMG,""));
27545a1e936bSStefano Zampini         if (ismatis && !matisok) {
27559566063dSJacob Faibussowitsch           PetscCall(MatConvert(M,MATAIJ,MAT_INPLACE_MATRIX,&M));
27565a1e936bSStefano Zampini         }
27575a1e936bSStefano Zampini       }
2758064a4176SStefano Zampini 
2759064a4176SStefano Zampini       /* run the subproblems to check convergence */
27609566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetBool(NULL,((PetscObject)newmat)->prefix,"-check_saddlepoint",&check,NULL));
2761064a4176SStefano Zampini       if (check) {
2762064a4176SStefano Zampini         PetscInt i;
2763064a4176SStefano Zampini 
2764064a4176SStefano Zampini         for (i=0;i<nn;i++) {
2765064a4176SStefano Zampini           KSP       kspC;
2766064a4176SStefano Zampini           PC        pc;
2767064a4176SStefano Zampini           Mat       F,pF;
2768064a4176SStefano Zampini           Vec       x,y;
2769064a4176SStefano Zampini           PetscBool isschur,prec = PETSC_TRUE;
2770064a4176SStefano Zampini 
27719566063dSJacob Faibussowitsch           PetscCall(KSPCreate(PetscObjectComm((PetscObject)ksps[i]),&kspC));
27729566063dSJacob Faibussowitsch           PetscCall(KSPSetOptionsPrefix(kspC,((PetscObject)ksps[i])->prefix));
27739566063dSJacob Faibussowitsch           PetscCall(KSPAppendOptionsPrefix(kspC,"check_"));
27749566063dSJacob Faibussowitsch           PetscCall(KSPGetOperators(ksps[i],&F,&pF));
27759566063dSJacob Faibussowitsch           PetscCall(PetscObjectTypeCompare((PetscObject)F,MATSCHURCOMPLEMENT,&isschur));
2776064a4176SStefano Zampini           if (isschur) {
2777064a4176SStefano Zampini             KSP  kspS,kspS2;
2778064a4176SStefano Zampini             Mat  A00,pA00,A10,A01,A11;
2779064a4176SStefano Zampini             char prefix[256];
2780064a4176SStefano Zampini 
27819566063dSJacob Faibussowitsch             PetscCall(MatSchurComplementGetKSP(F,&kspS));
27829566063dSJacob Faibussowitsch             PetscCall(MatSchurComplementGetSubMatrices(F,&A00,&pA00,&A01,&A10,&A11));
27839566063dSJacob Faibussowitsch             PetscCall(MatCreateSchurComplement(A00,pA00,A01,A10,A11,&F));
27849566063dSJacob Faibussowitsch             PetscCall(MatSchurComplementGetKSP(F,&kspS2));
27859566063dSJacob Faibussowitsch             PetscCall(PetscSNPrintf(prefix,sizeof(prefix),"%sschur_",((PetscObject)kspC)->prefix));
27869566063dSJacob Faibussowitsch             PetscCall(KSPSetOptionsPrefix(kspS2,prefix));
27879566063dSJacob Faibussowitsch             PetscCall(KSPGetPC(kspS2,&pc));
27889566063dSJacob Faibussowitsch             PetscCall(PCSetType(pc,PCKSP));
27899566063dSJacob Faibussowitsch             PetscCall(PCKSPSetKSP(pc,kspS));
27909566063dSJacob Faibussowitsch             PetscCall(KSPSetFromOptions(kspS2));
27919566063dSJacob Faibussowitsch             PetscCall(KSPGetPC(kspS2,&pc));
27929566063dSJacob Faibussowitsch             PetscCall(PCSetUseAmat(pc,PETSC_TRUE));
2793064a4176SStefano Zampini           } else {
27949566063dSJacob Faibussowitsch             PetscCall(PetscObjectReference((PetscObject)F));
2795064a4176SStefano Zampini           }
27969566063dSJacob Faibussowitsch           PetscCall(KSPSetFromOptions(kspC));
27979566063dSJacob Faibussowitsch           PetscCall(PetscOptionsGetBool(NULL,((PetscObject)kspC)->prefix,"-preconditioned",&prec,NULL));
2798064a4176SStefano Zampini           if (prec)  {
27999566063dSJacob Faibussowitsch             PetscCall(KSPGetPC(ksps[i],&pc));
28009566063dSJacob Faibussowitsch             PetscCall(KSPSetPC(kspC,pc));
2801064a4176SStefano Zampini           }
28029566063dSJacob Faibussowitsch           PetscCall(KSPSetOperators(kspC,F,pF));
28039566063dSJacob Faibussowitsch           PetscCall(MatCreateVecs(F,&x,&y));
28049566063dSJacob Faibussowitsch           PetscCall(VecSetRandom(x,NULL));
28059566063dSJacob Faibussowitsch           PetscCall(MatMult(F,x,y));
28069566063dSJacob Faibussowitsch           PetscCall(KSPSolve(kspC,y,x));
28079566063dSJacob Faibussowitsch           PetscCall(KSPCheckSolve(kspC,pc,x));
28089566063dSJacob Faibussowitsch           PetscCall(KSPDestroy(&kspC));
28099566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&F));
28109566063dSJacob Faibussowitsch           PetscCall(VecDestroy(&x));
28119566063dSJacob Faibussowitsch           PetscCall(VecDestroy(&y));
2812064a4176SStefano Zampini         }
2813064a4176SStefano Zampini       }
28149566063dSJacob Faibussowitsch       PetscCall(PetscFree(ksps));
2815e1214c54Sstefano_zampini     }
28165a1e936bSStefano Zampini   }
28173425bc38SStefano Zampini   /* return pointers for objects created */
28183425bc38SStefano Zampini   *fetidp_mat = newmat;
28193425bc38SStefano Zampini   *fetidp_pc  = newpc;
28203425bc38SStefano Zampini   PetscFunctionReturn(0);
28213425bc38SStefano Zampini }
28221e6b0712SBarry Smith 
282394ef8ddeSSatish Balay /*@C
28240f202f7eSStefano Zampini  PCBDDCCreateFETIDPOperators - Create FETI-DP operators
28253425bc38SStefano Zampini 
28263425bc38SStefano Zampini    Collective
28273425bc38SStefano Zampini 
28283425bc38SStefano Zampini    Input Parameters:
28291720468bSStefano Zampini +  pc - the BDDC preconditioning context (setup should have been called before)
2830547c9a8eSstefano_zampini .  fully_redundant - true for a fully redundant set of Lagrange multipliers
2831547c9a8eSstefano_zampini -  prefix - optional options database prefix for the objects to be created (can be NULL)
283228509bceSStefano Zampini 
283328509bceSStefano Zampini    Output Parameters:
28340f202f7eSStefano Zampini +  fetidp_mat - shell FETI-DP matrix object
28350f202f7eSStefano Zampini -  fetidp_pc  - shell Dirichlet preconditioner for FETI-DP matrix
283628509bceSStefano Zampini 
28373425bc38SStefano Zampini    Level: developer
28383425bc38SStefano Zampini 
28393425bc38SStefano Zampini    Notes:
28400f202f7eSStefano Zampini      Currently the only operations provided for FETI-DP matrix are MatMult and MatMultTranspose
28413425bc38SStefano Zampini 
284216b07851SJed Brown .seealso: `PCBDDC`, `PCBDDCMatFETIDPGetRHS()`, `PCBDDCMatFETIDPGetSolution()`
28433425bc38SStefano Zampini @*/
2844547c9a8eSstefano_zampini PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc)
28453425bc38SStefano Zampini {
28463425bc38SStefano Zampini   PetscFunctionBegin;
28473425bc38SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
28483425bc38SStefano Zampini   if (pc->setupcalled) {
2849cac4c232SBarry Smith     PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,PetscBool,const char*,Mat*,PC*),(pc,fully_redundant,prefix,fetidp_mat,fetidp_pc));
28506080607fSStefano Zampini   } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"You must call PCSetup_BDDC() first");
28513425bc38SStefano Zampini   PetscFunctionReturn(0);
28523425bc38SStefano Zampini }
28530c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
2854da1bb401SStefano Zampini /*MC
2855da1bb401SStefano Zampini    PCBDDC - Balancing Domain Decomposition by Constraints.
28560c7d97c5SJed Brown 
2857be4a8d98Sprj-    An implementation of the BDDC preconditioner based on the bibliography found below.
285828509bceSStefano Zampini 
285928509bceSStefano Zampini    The matrix to be preconditioned (Pmat) must be of type MATIS.
286028509bceSStefano Zampini 
28610f202f7eSStefano Zampini    Currently works with MATIS matrices with local matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers.
286228509bceSStefano Zampini 
286328509bceSStefano Zampini    It also works with unsymmetric and indefinite problems.
286428509bceSStefano Zampini 
2865b6fdb6dfSStefano 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.
2866b6fdb6dfSStefano Zampini 
2867c7017625SStefano 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).
286828509bceSStefano Zampini 
28690f202f7eSStefano 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()
287030368db7SStefano Zampini    Additional information on dofs can be provided by using PCBDDCSetDofsSplitting(), PCBDDCSetDirichletBoundaries(), PCBDDCSetNeumannBoundaries(), and PCBDDCSetPrimalVerticesIS() and their local counterparts.
287128509bceSStefano Zampini 
28720f202f7eSStefano Zampini    Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). Non-singular modes are retained via SVD.
287328509bceSStefano Zampini 
28740f202f7eSStefano 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.
28750f202f7eSStefano Zampini    User defined change of basis can be passed to PCBDDC by using PCBDDCSetChangeOfBasisMat()
287628509bceSStefano Zampini 
28770f202f7eSStefano Zampini    The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using a MatPartitioning object.
287828509bceSStefano Zampini 
2879df4d28bfSStefano 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.
288028509bceSStefano Zampini 
28810f202f7eSStefano 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.
28820f202f7eSStefano Zampini 
2883d314f959SVaclav Hapla    Options Database Keys (some of them, run with -help for a complete list):
28840f202f7eSStefano Zampini 
2885a2b725a8SWilliam Gropp +    -pc_bddc_use_vertices <true> - use or not vertices in primal space
28860f202f7eSStefano Zampini .    -pc_bddc_use_edges <true> - use or not edges in primal space
28870f202f7eSStefano Zampini .    -pc_bddc_use_faces <false> - use or not faces in primal space
28880f202f7eSStefano Zampini .    -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems
28890f202f7eSStefano Zampini .    -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only)
28900f202f7eSStefano Zampini .    -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested
28910f202f7eSStefano Zampini .    -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1])
289228509bceSStefano Zampini .    -pc_bddc_levels <0> - maximum number of levels for multilevel
28930f202f7eSStefano 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)
28945459c157SBarry 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)
28950f202f7eSStefano Zampini .    -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling
289671f2caa7Sprj- .    -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)
2897bd2a564bSStefano 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)
289828509bceSStefano Zampini -    -pc_bddc_check_level <0> - set verbosity level of debugging output
289928509bceSStefano Zampini 
290028509bceSStefano Zampini    Options for Dirichlet, Neumann or coarse solver can be set with
290128509bceSStefano Zampini .vb
290228509bceSStefano Zampini       -pc_bddc_dirichlet_
290328509bceSStefano Zampini       -pc_bddc_neumann_
290428509bceSStefano Zampini       -pc_bddc_coarse_
290528509bceSStefano Zampini .ve
2906f9ff08acSPierre Jolivet    e.g. -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. PCBDDC uses by default KSPPREONLY and PCLU.
290728509bceSStefano Zampini 
29080f202f7eSStefano Zampini    When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified as
290928509bceSStefano Zampini .vb
2910312be037SStefano Zampini       -pc_bddc_dirichlet_lN_
2911312be037SStefano Zampini       -pc_bddc_neumann_lN_
2912312be037SStefano Zampini       -pc_bddc_coarse_lN_
291328509bceSStefano Zampini .ve
29140f202f7eSStefano Zampini    Note that level number ranges from the finest (0) to the coarsest (N).
29150f202f7eSStefano 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.
29160f202f7eSStefano Zampini .vb
29170f202f7eSStefano Zampini      -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3
29180f202f7eSStefano Zampini .ve
29190f202f7eSStefano 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
2920da1bb401SStefano Zampini 
2921be4a8d98Sprj-    References:
2922606c0280SSatish Balay +  * - C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149--168, March 2007
2923606c0280SSatish 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
2924606c0280SSatish Balay .  * - J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", Computing Volume 83, Issue 2--3, pages 55--85, November 2008
2925606c0280SSatish 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
2926be4a8d98Sprj- 
2927da1bb401SStefano Zampini    Level: intermediate
2928da1bb401SStefano Zampini 
2929e94cfbe0SPatrick Sanan    Developer Notes:
2930da1bb401SStefano Zampini 
2931da1bb401SStefano Zampini    Contributed by Stefano Zampini
2932da1bb401SStefano Zampini 
2933db781477SPatrick Sanan .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `MATIS`
2934da1bb401SStefano Zampini M*/
2935b2573a8aSBarry Smith 
29368cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
2937da1bb401SStefano Zampini {
2938da1bb401SStefano Zampini   PC_BDDC             *pcbddc;
2939da1bb401SStefano Zampini 
2940da1bb401SStefano Zampini   PetscFunctionBegin;
29419566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(pc,&pcbddc));
29423ec1f749SStefano Zampini   pc->data = pcbddc;
2943da1bb401SStefano Zampini 
2944da1bb401SStefano Zampini   /* create PCIS data structure */
29459566063dSJacob Faibussowitsch   PetscCall(PCISCreate(pc));
2946da1bb401SStefano Zampini 
29479326c5c6Sstefano_zampini   /* create local graph structure */
29489566063dSJacob Faibussowitsch   PetscCall(PCBDDCGraphCreate(&pcbddc->mat_graph));
29499326c5c6Sstefano_zampini 
29509326c5c6Sstefano_zampini   /* BDDC nonzero defaults */
29516d9e27e4SStefano Zampini   pcbddc->use_nnsp                  = PETSC_TRUE;
295208a5cf49SStefano Zampini   pcbddc->use_local_adj             = PETSC_TRUE;
295347d04d0dSStefano Zampini   pcbddc->use_vertices              = PETSC_TRUE;
295447d04d0dSStefano Zampini   pcbddc->use_edges                 = PETSC_TRUE;
29553301b35fSStefano Zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
295614f95afaSStefano Zampini   pcbddc->vertex_size               = 1;
2957c703fcc7SStefano Zampini   pcbddc->recompute_topography      = PETSC_TRUE;
295868457ee5SStefano Zampini   pcbddc->coarse_size               = -1;
295985c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
296047d04d0dSStefano Zampini   pcbddc->coarsening_ratio          = 8;
296157de7509SStefano Zampini   pcbddc->coarse_eqs_per_proc       = 1;
296227b6a85dSStefano Zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
29631e0482f5SStefano Zampini   pcbddc->nedfield                  = -1;
29641e0482f5SStefano Zampini   pcbddc->nedglobal                 = PETSC_TRUE;
2965be12c134Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
2966b96c3477SStefano Zampini   pcbddc->sub_schurs_layers         = -1;
2967bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[0]     = 0.0;
2968bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[1]     = 0.0;
2969b7eb3628SStefano Zampini 
2970da1bb401SStefano Zampini   /* function pointers */
2971da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
297293bd9ae7SStefano Zampini   pc->ops->applytranspose      = PCApplyTranspose_BDDC;
2973da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
2974da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
2975da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
29766b78500eSPatrick Sanan   pc->ops->view                = PCView_BDDC;
29770a545947SLisandro Dalcin   pc->ops->applyrichardson     = NULL;
29780a545947SLisandro Dalcin   pc->ops->applysymmetricleft  = NULL;
29790a545947SLisandro Dalcin   pc->ops->applysymmetricright = NULL;
2980534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
2981534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
29829326c5c6Sstefano_zampini   pc->ops->reset               = PCReset_BDDC;
2983da1bb401SStefano Zampini 
2984da1bb401SStefano Zampini   /* composing function */
29859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",PCBDDCSetDiscreteGradient_BDDC));
29869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",PCBDDCSetDivergenceMat_BDDC));
29879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",PCBDDCSetChangeOfBasisMat_BDDC));
29889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC));
29899566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",PCBDDCSetPrimalVerticesIS_BDDC));
29909566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesLocalIS_C",PCBDDCGetPrimalVerticesLocalIS_BDDC));
29919566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesIS_C",PCBDDCGetPrimalVerticesIS_BDDC));
29929566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC));
29939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC));
29949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC));
29959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC));
29969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC));
29979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",PCBDDCSetDirichletBoundariesLocal_BDDC));
29989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC));
29999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",PCBDDCSetNeumannBoundariesLocal_BDDC));
30009566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC));
30019566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",PCBDDCGetDirichletBoundariesLocal_BDDC));
30029566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC));
30039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",PCBDDCGetNeumannBoundariesLocal_BDDC));
30049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC));
30059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",PCBDDCSetDofsSplittingLocal_BDDC));
30069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC));
30079566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC));
30089566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC));
30099566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC));
30109566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",PCPreSolveChangeRHS_BDDC));
30119566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",PCSetCoordinates_BDDC));
3012da1bb401SStefano Zampini   PetscFunctionReturn(0);
3013da1bb401SStefano Zampini }
301443371fb9SStefano Zampini 
301543371fb9SStefano Zampini /*@C
301643371fb9SStefano Zampini  PCBDDCInitializePackage - This function initializes everything in the PCBDDC package. It is called
30178a690491SBarry Smith     from PCInitializePackage().
301843371fb9SStefano Zampini 
301943371fb9SStefano Zampini  Level: developer
302043371fb9SStefano Zampini 
3021db781477SPatrick Sanan  .seealso: `PetscInitialize()`
302243371fb9SStefano Zampini @*/
302343371fb9SStefano Zampini PetscErrorCode PCBDDCInitializePackage(void)
302443371fb9SStefano Zampini {
302543371fb9SStefano Zampini   int            i;
302643371fb9SStefano Zampini 
302743371fb9SStefano Zampini   PetscFunctionBegin;
302843371fb9SStefano Zampini   if (PCBDDCPackageInitialized) PetscFunctionReturn(0);
302943371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_TRUE;
30309566063dSJacob Faibussowitsch   PetscCall(PetscRegisterFinalize(PCBDDCFinalizePackage));
303143371fb9SStefano Zampini 
303243371fb9SStefano Zampini   /* general events */
30339566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCTopo",PC_CLASSID,&PC_BDDC_Topology[0]));
30349566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCLKSP",PC_CLASSID,&PC_BDDC_LocalSolvers[0]));
30359566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCLWor",PC_CLASSID,&PC_BDDC_LocalWork[0]));
30369566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCorr",PC_CLASSID,&PC_BDDC_CorrectionSetUp[0]));
30379566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCASet",PC_CLASSID,&PC_BDDC_ApproxSetUp[0]));
30389566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCAApp",PC_CLASSID,&PC_BDDC_ApproxApply[0]));
30399566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCSet",PC_CLASSID,&PC_BDDC_CoarseSetUp[0]));
30409566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCKSP",PC_CLASSID,&PC_BDDC_CoarseSolver[0]));
30419566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCAdap",PC_CLASSID,&PC_BDDC_AdaptiveSetUp[0]));
30429566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCScal",PC_CLASSID,&PC_BDDC_Scaling[0]));
30439566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCSchr",PC_CLASSID,&PC_BDDC_Schurs[0]));
30449566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCDirS",PC_CLASSID,&PC_BDDC_Solves[0][0]));
30459566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCNeuS",PC_CLASSID,&PC_BDDC_Solves[0][1]));
30469566063dSJacob Faibussowitsch   PetscCall(PetscLogEventRegister("PCBDDCCoaS",PC_CLASSID,&PC_BDDC_Solves[0][2]));
304743371fb9SStefano Zampini   for (i=1;i<PETSC_PCBDDC_MAXLEVELS;i++) {
304843371fb9SStefano Zampini     char ename[32];
304943371fb9SStefano Zampini 
30509566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCTopo l%02d",i));
30519566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Topology[i]));
30529566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCLKSP l%02d",i));
30539566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_LocalSolvers[i]));
30549566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCLWor l%02d",i));
30559566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_LocalWork[i]));
30569566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCCorr l%02d",i));
30579566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CorrectionSetUp[i]));
30589566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCASet l%02d",i));
30599566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_ApproxSetUp[i]));
30609566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCAApp l%02d",i));
30619566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_ApproxApply[i]));
30629566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCCSet l%02d",i));
30639566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CoarseSetUp[i]));
30649566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCCKSP l%02d",i));
30659566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CoarseSolver[i]));
30669566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCAdap l%02d",i));
30679566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_AdaptiveSetUp[i]));
30689566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCScal l%02d",i));
30699566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Scaling[i]));
30709566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCSchr l%02d",i));
30719566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Schurs[i]));
30729566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCDirS l%02d",i));
30739566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Solves[i][0]));
30749566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCNeuS l%02d",i));
30759566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Solves[i][1]));
30769566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(ename,sizeof(ename),"PCBDDCCoaS l%02d",i));
30779566063dSJacob Faibussowitsch     PetscCall(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Solves[i][2]));
307843371fb9SStefano Zampini   }
307943371fb9SStefano Zampini   PetscFunctionReturn(0);
308043371fb9SStefano Zampini }
308143371fb9SStefano Zampini 
308243371fb9SStefano Zampini /*@C
308343371fb9SStefano Zampini  PCBDDCFinalizePackage - This function frees everything from the PCBDDC package. It is
308443371fb9SStefano Zampini     called from PetscFinalize() automatically.
308543371fb9SStefano Zampini 
308643371fb9SStefano Zampini  Level: developer
308743371fb9SStefano Zampini 
3088db781477SPatrick Sanan  .seealso: `PetscFinalize()`
308943371fb9SStefano Zampini @*/
309043371fb9SStefano Zampini PetscErrorCode PCBDDCFinalizePackage(void)
309143371fb9SStefano Zampini {
309243371fb9SStefano Zampini   PetscFunctionBegin;
309343371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_FALSE;
309443371fb9SStefano Zampini   PetscFunctionReturn(0);
309543371fb9SStefano Zampini }
3096