xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 28b400f66ebc7ae0049166a2294dfcd3df27e64b)
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 
22ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddc.h> /*I "petscpc.h" I*/  /* includes for fortran wrappers */
23ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddcprivate.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;
665f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsHead(PetscOptionsObject,"BDDC options"));
678eeda7d8SStefano Zampini   /* Verbose debugging */
685f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsInt("-pc_bddc_check_level","Verbose output for PCBDDC (intended for debug)","none",pcbddc->dbg_flag,&pcbddc->dbg_flag,NULL));
69a13144ffSStefano Zampini   /* Approximate solvers */
705f80ce2aSJacob Faibussowitsch   CHKERRQ(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) {
725f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsBool("-pc_bddc_dirichlet_approximate","Inform PCBDDC that we are using approximate Dirichlet solvers","none",pcbddc->NullSpace_corr[0],&pcbddc->NullSpace_corr[0],NULL));
735f80ce2aSJacob Faibussowitsch     CHKERRQ(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   }
785f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-pc_bddc_neumann_approximate","Inform PCBDDC that we are using approximate Neumann solvers","none",pcbddc->NullSpace_corr[2],&pcbddc->NullSpace_corr[2],NULL));
795f80ce2aSJacob Faibussowitsch   CHKERRQ(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 */
815f80ce2aSJacob Faibussowitsch   CHKERRQ(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));
825f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsInt("-pc_bddc_graph_maxcount","Maximum number of shared subdomains for a connected component","none",pcbddc->graphmaxcount,&pcbddc->graphmaxcount,NULL));
835f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-pc_bddc_corner_selection","Activates face-based corner selection","none",pcbddc->corner_selection,&pcbddc->corner_selection,NULL));
845f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-pc_bddc_use_vertices","Use or not corner dofs in coarse space","none",pcbddc->use_vertices,&pcbddc->use_vertices,NULL));
855f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-pc_bddc_use_edges","Use or not edge constraints in coarse space","none",pcbddc->use_edges,&pcbddc->use_edges,NULL));
865f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-pc_bddc_use_faces","Use or not face constraints in coarse space","none",pcbddc->use_faces,&pcbddc->use_faces,NULL));
875f80ce2aSJacob Faibussowitsch   CHKERRQ(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));
885f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-pc_bddc_use_nnsp","Use near null space attached to the matrix to compute constraints","none",pcbddc->use_nnsp,&pcbddc->use_nnsp,NULL));
895f80ce2aSJacob Faibussowitsch   CHKERRQ(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));
905f80ce2aSJacob Faibussowitsch   CHKERRQ(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 */
925f80ce2aSJacob Faibussowitsch   CHKERRQ(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));
935f80ce2aSJacob Faibussowitsch   CHKERRQ(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) */
985f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-pc_bddc_switch_static","Switch on static condensation ops around the interface preconditioner","none",pcbddc->switch_static,&pcbddc->switch_static,NULL));
995f80ce2aSJacob Faibussowitsch   CHKERRQ(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;
1015f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","PCBDDCSetCoarseningRatio",i,&i,NULL));
1025f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCSetCoarseningRatio(pc,i));
103e569e4e1SStefano Zampini   i    = pcbddc->max_levels;
1045f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsInt("-pc_bddc_levels","Set maximum number of levels for multilevel","PCBDDCSetLevels",i,&i,NULL));
1055f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCSetLevels(pc,i));
1065f80ce2aSJacob Faibussowitsch   CHKERRQ(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));
1075f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-pc_bddc_use_coarse_estimates","Use estimated eigenvalues for coarse problem","none",pcbddc->use_coarse_estimates,&pcbddc->use_coarse_estimates,NULL));
1085f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-pc_bddc_use_deluxe_scaling","Use deluxe scaling for BDDC","none",pcbddc->use_deluxe_scaling,&pcbddc->use_deluxe_scaling,NULL));
1095f80ce2aSJacob Faibussowitsch   CHKERRQ(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));
1105f80ce2aSJacob Faibussowitsch   CHKERRQ(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));
1115f80ce2aSJacob Faibussowitsch   CHKERRQ(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));
1125f80ce2aSJacob Faibussowitsch   CHKERRQ(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));
1135f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-pc_bddc_deluxe_zerorows","Zero rows and columns of deluxe operators associated with primal dofs","none",pcbddc->deluxe_zerorows,&pcbddc->deluxe_zerorows,NULL));
1145f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-pc_bddc_deluxe_singlemat","Collapse deluxe operators","none",pcbddc->deluxe_singlemat,&pcbddc->deluxe_singlemat,NULL));
1155f80ce2aSJacob Faibussowitsch   CHKERRQ(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;
1175f80ce2aSJacob Faibussowitsch   CHKERRQ(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];
1195f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsInt("-pc_bddc_adaptive_nmin","Minimum number of constraints per connected components","none",pcbddc->adaptive_nmin,&pcbddc->adaptive_nmin,NULL));
1205f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsInt("-pc_bddc_adaptive_nmax","Maximum number of constraints per connected components","none",pcbddc->adaptive_nmax,&pcbddc->adaptive_nmax,NULL));
1215f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-pc_bddc_symmetric","Symmetric computation of primal basis functions","none",pcbddc->symmetric_primal,&pcbddc->symmetric_primal,NULL));
1225f80ce2aSJacob Faibussowitsch   CHKERRQ(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));
1235f80ce2aSJacob Faibussowitsch   CHKERRQ(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));
1245f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-pc_bddc_benign_change","Compute the pressure change of basis explicitly","none",pcbddc->benign_change_explicit,&pcbddc->benign_change_explicit,NULL));
1255f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-pc_bddc_benign_compute_correction","Compute the benign correction during PreSolve","none",pcbddc->benign_compute_correction,&pcbddc->benign_compute_correction,NULL));
1265f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-pc_bddc_nonetflux","Automatic computation of no-net-flux quadrature weights","none",pcbddc->compute_nonetflux,&pcbddc->compute_nonetflux,NULL));
1275f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-pc_bddc_detect_disconnected","Detects disconnected subdomains","none",pcbddc->detect_disconnected,&pcbddc->detect_disconnected,NULL));
1285f80ce2aSJacob Faibussowitsch   CHKERRQ(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));
1295f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-pc_bddc_eliminate_dirichlet","Whether or not we want to eliminate dirichlet dofs during presolve","none",pcbddc->eliminate_dirdofs,&pcbddc->eliminate_dirdofs,NULL));
1305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsTail());
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;
1435f80ce2aSJacob Faibussowitsch   CHKERRQ(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) {
1535f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Partial information available: preconditioner has not been setup yet\n"));
154b74ba07aSstefano_zampini     }
1555f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Use verbose output: %D\n",pcbddc->dbg_flag));
1565f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Use user-defined CSR: %d\n",!!pcbddc->mat_graph->nvtxs_csr));
1575f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Use local mat graph: %d\n",pcbddc->use_local_adj && !pcbddc->mat_graph->nvtxs_csr));
158e9627c49SStefano Zampini     if (pcbddc->mat_graph->twodim) {
1595f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Connectivity graph topological dimension: 2\n"));
160e9627c49SStefano Zampini     } else {
1615f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Connectivity graph topological dimension: 3\n"));
162e9627c49SStefano Zampini     }
163aefa1729SStefano Zampini     if (pcbddc->graphmaxcount != PETSC_MAX_INT) {
1645f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Graph max count: %D\n",pcbddc->graphmaxcount));
165aefa1729SStefano Zampini     }
1665f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Corner selection: %d (selected %d)\n",pcbddc->corner_selection,pcbddc->corner_selected));
1675f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Use vertices: %d (vertex size %D)\n",pcbddc->use_vertices,pcbddc->vertex_size));
1685f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Use edges: %d\n",pcbddc->use_edges));
1695f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Use faces: %d\n",pcbddc->use_faces));
1705f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Use true near null space: %d\n",pcbddc->use_nnsp_true));
1715f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Use QR for single constraints on cc: %d\n",pcbddc->use_qr_single));
1725f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Use change of basis on local edge nodes: %d\n",pcbddc->use_change_of_basis));
1735f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Use change of basis on local face nodes: %d\n",pcbddc->use_change_on_faces));
1745f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  User defined change of basis matrix: %d\n",!!pcbddc->user_ChangeOfBasisMatrix));
1755f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Has change of basis matrix: %d\n",!!pcbddc->ChangeOfBasisMatrix));
1765f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Eliminate dirichlet boundary dofs: %d\n",pcbddc->eliminate_dirdofs));
1775f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Switch on static condensation ops around the interface preconditioner: %d\n",pcbddc->switch_static));
1785f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Use exact dirichlet trick: %d\n",pcbddc->use_exact_dirichlet_trick));
1795f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Interface extension: %s\n",PCBDDCInterfaceExtTypes[pcbddc->interface_extension]));
1805f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Multilevel max levels: %D\n",pcbddc->max_levels));
1815f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Multilevel coarsening ratio: %D\n",pcbddc->coarsening_ratio));
1825f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Use estimated eigs for coarse problem: %d\n",pcbddc->use_coarse_estimates));
1835f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Use deluxe scaling: %d\n",pcbddc->use_deluxe_scaling));
1845f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Use deluxe zerorows: %d\n",pcbddc->deluxe_zerorows));
1855f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Use deluxe singlemat: %d\n",pcbddc->deluxe_singlemat));
1865f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Rebuild interface graph for Schur principal minors: %d\n",pcbddc->sub_schurs_rebuild));
1875f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Number of dofs' layers for the computation of principal minors: %D\n",pcbddc->sub_schurs_layers));
1885f80ce2aSJacob Faibussowitsch     CHKERRQ(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]) {
1905f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Adaptive constraint selection thresholds (active %d, userdefined %d): %g,%g\n",pcbddc->adaptive_selection,pcbddc->adaptive_userdefined,pcbddc->adaptive_threshold[0],pcbddc->adaptive_threshold[1]));
191bd2a564bSStefano Zampini     } else {
1925f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Adaptive constraint selection threshold (active %d, userdefined %d): %g\n",pcbddc->adaptive_selection,pcbddc->adaptive_userdefined,pcbddc->adaptive_threshold[0]));
193bd2a564bSStefano Zampini     }
1945f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Min constraints / connected component: %D\n",pcbddc->adaptive_nmin));
1955f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Max constraints / connected component: %D\n",pcbddc->adaptive_nmax));
1965f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Invert exact Schur complement for adaptive selection: %d\n",pcbddc->sub_schurs_exact_schur));
1975f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Symmetric computation of primal basis functions: %d\n",pcbddc->symmetric_primal));
1985f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Num. Procs. to map coarse adjacency list: %D\n",pcbddc->coarse_adj_red));
1995f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Coarse eqs per proc (significant at the coarsest level): %D\n",pcbddc->coarse_eqs_per_proc));
2005f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Detect disconnected: %d (filter %d)\n",pcbddc->detect_disconnected,pcbddc->detect_disconnected_filter));
2015f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Benign subspace trick: %d (change explicit %d)\n",pcbddc->benign_saddle_point,pcbddc->benign_change_explicit));
2025f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Benign subspace trick is active: %d\n",pcbddc->benign_have_null));
2035f80ce2aSJacob Faibussowitsch     CHKERRQ(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 */
2075f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSet(pcis->vec1_B,1.0));
2085f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreateVecs(pc->pmat,&counter,NULL));
2095f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSet(counter,0.0));
2105f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterBegin(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE));
2115f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterEnd(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE));
2125f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSum(counter,&interface_size));
2135f80ce2aSJacob Faibussowitsch     CHKERRQ(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;
2255f80ce2aSJacob Faibussowitsch     CHKERRMPI(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;
2275f80ce2aSJacob Faibussowitsch     CHKERRMPI(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;
2295f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(loc,gmin,6,MPIU_INT64,MPI_MIN,0,PetscObjectComm((PetscObject)pc)));
2305f80ce2aSJacob Faibussowitsch     CHKERRMPI(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     }
2355f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"********************************** STATISTICS AT LEVEL %d **********************************\n",pcbddc->current_level));
2365f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Global dofs sizes: all %D interface %D coarse %D\n",pc->pmat->rmap->N,(PetscInt)PetscRealPart(interface_size),pcbddc->coarse_size));
2375f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Coarsening ratios: all/coarse %D interface/coarse %D\n",(PetscInt)ratio1,(PetscInt)ratio2));
2385f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Active processes : %D\n",(PetscInt)gsum[0]));
2395f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Total subdomains : %D\n",(PetscInt)gsum[5]));
240345ecf6cSStefano Zampini     if (pcbddc->benign_have_null) {
2415f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Benign subs      : %D\n",(PetscInt)totbenign));
242345ecf6cSStefano Zampini     }
2435f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Dofs type        :\tMIN\tMAX\tMEAN\n"));
2445f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Interior  dofs   :\t%D\t%D\t%D\n",(PetscInt)gmin[1],(PetscInt)gmax[1],(PetscInt)(gsum[1]/gsum[0])));
2455f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Interface dofs   :\t%D\t%D\t%D\n",(PetscInt)gmin[2],(PetscInt)gmax[2],(PetscInt)(gsum[2]/gsum[0])));
2465f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Primal    dofs   :\t%D\t%D\t%D\n",(PetscInt)gmin[3],(PetscInt)gmax[3],(PetscInt)(gsum[3]/gsum[0])));
2475f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Local     dofs   :\t%D\t%D\t%D\n",(PetscInt)gmin[4],(PetscInt)gmax[4],(PetscInt)(gsum[4]/gsum[0])));
2485f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"  Local     subs   :\t%D\t%D\n"    ,(PetscInt)gmin[5],(PetscInt)gmax[5]));
2495f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerFlush(viewer));
25015579a77SStefano Zampini 
2515f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank));
25215579a77SStefano Zampini 
25315579a77SStefano Zampini     /* local solvers */
2545f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerGetSubViewer(viewer,PetscObjectComm((PetscObject)pcbddc->ksp_D),&subviewer));
255dd400576SPatrick Sanan     if (rank == 0) {
2565f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(subviewer,"--- Interior solver (rank 0)\n"));
2575f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPushTab(subviewer));
2585f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPView(pcbddc->ksp_D,subviewer));
2595f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPopTab(subviewer));
2605f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(subviewer,"--- Correction solver (rank 0)\n"));
2615f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPushTab(subviewer));
2625f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPView(pcbddc->ksp_R,subviewer));
2635f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPopTab(subviewer));
2645f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerFlush(subviewer));
26515579a77SStefano Zampini     }
2665f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerRestoreSubViewer(viewer,PetscObjectComm((PetscObject)pcbddc->ksp_D),&subviewer));
2675f80ce2aSJacob Faibussowitsch     CHKERRQ(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;
2725f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size));
2735f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSubcommCreate(PetscObjectComm((PetscObject)pc),&subcomm));
2745f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSubcommSetNumber(subcomm,PetscMin(size,2)));
2755f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSubcommSetTypeGeneral(subcomm,color,rank));
2765f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerGetSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer));
277e9627c49SStefano Zampini     if (color == 1) {
2785f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(subviewer,"--- Coarse solver\n"));
2795f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPushTab(subviewer));
2805f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPView(pcbddc->coarse_ksp,subviewer));
2815f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPopTab(subviewer));
2825f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerFlush(subviewer));
283e9627c49SStefano Zampini     }
2845f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerRestoreSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer));
2855f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSubcommDestroy(&subcomm));
2865f80ce2aSJacob Faibussowitsch     CHKERRQ(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;
2965f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference((PetscObject)G));
2975f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
329495a2a07SStefano Zampini .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);
3415f80ce2aSJacob Faibussowitsch   CHKERRQ(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;
3505f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference((PetscObject)divudotp));
3515f80ce2aSJacob Faibussowitsch   CHKERRQ(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) {
3565f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectReference((PetscObject)vl2l));
3575f80ce2aSJacob Faibussowitsch     CHKERRQ(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 
380a198735bSStefano Zampini .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);
3925f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)divudotp,MATIS,&ismatis));
393*28b400f6SJacob Faibussowitsch   PetscCheck(ismatis,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Divergence matrix needs to be of type MATIS");
3945f80ce2aSJacob Faibussowitsch   CHKERRQ(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;
4035f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference((PetscObject)change));
4045f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
423b9b85e73SStefano Zampini .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;
4335f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetSize(pc->mat,&rows,&cols));
4345f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetSize(change,&rows_c,&cols_c));
4352c71b3e2SJacob Faibussowitsch     PetscCheckFalse(rows_c != rows,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of rows for change of basis matrix! %D != %D",rows_c,rows);
4362c71b3e2SJacob Faibussowitsch     PetscCheckFalse(cols_c != cols,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of columns for change of basis matrix! %D != %D",cols_c,cols);
4375f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetLocalSize(pc->mat,&rows,&cols));
4385f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetLocalSize(change,&rows_c,&cols_c));
4392c71b3e2SJacob Faibussowitsch     PetscCheckFalse(rows_c != rows,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of local rows for change of basis matrix! %D != %D",rows_c,rows);
4402c71b3e2SJacob Faibussowitsch     PetscCheckFalse(cols_c != cols,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of local columns for change of basis matrix! %D != %D",cols_c,cols);
441906d46d4SStefano Zampini   }
4425f80ce2aSJacob Faibussowitsch   CHKERRQ(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;
4525f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference((PetscObject)PrimalVertices));
45356282151SStefano Zampini   if (pcbddc->user_primal_vertices) {
4545f80ce2aSJacob Faibussowitsch     CHKERRQ(ISEqual(PrimalVertices,pcbddc->user_primal_vertices,&isequal));
45556282151SStefano Zampini   }
4565f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&pcbddc->user_primal_vertices));
4575f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
4773100ebe3SStefano Zampini .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);
4855f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
5133100ebe3SStefano Zampini .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);
5205f80ce2aSJacob Faibussowitsch   CHKERRQ(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;
5305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference((PetscObject)PrimalVertices));
53156282151SStefano Zampini   if (pcbddc->user_primal_vertices_local) {
5325f80ce2aSJacob Faibussowitsch     CHKERRQ(ISEqual(PrimalVertices,pcbddc->user_primal_vertices_local,&isequal));
53356282151SStefano Zampini   }
5345f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&pcbddc->user_primal_vertices));
5355f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
5543100ebe3SStefano Zampini .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);
5625f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
5903100ebe3SStefano Zampini .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);
5975f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
6270f202f7eSStefano Zampini .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);
6345f80ce2aSJacob Faibussowitsch   CHKERRQ(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);
6535f80ce2aSJacob Faibussowitsch   CHKERRQ(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);
6715f80ce2aSJacob Faibussowitsch   CHKERRQ(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;
6802c71b3e2SJacob Faibussowitsch   PetscCheckFalse(levels > PETSC_PCBDDC_MAXLEVELS-1,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 
7020f202f7eSStefano Zampini .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);
7095f80ce2aSJacob Faibussowitsch   CHKERRQ(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;
7195f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference((PetscObject)DirichletBoundaries));
72056282151SStefano Zampini   if (pcbddc->DirichletBoundaries) {
7215f80ce2aSJacob Faibussowitsch     CHKERRQ(ISEqual(DirichletBoundaries,pcbddc->DirichletBoundaries,&isequal));
72256282151SStefano Zampini   }
723a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
7245f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&pcbddc->DirichletBoundariesLocal));
7255f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
7450f202f7eSStefano Zampini .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);
7535f80ce2aSJacob Faibussowitsch   CHKERRQ(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;
7635f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference((PetscObject)DirichletBoundaries));
76456282151SStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
7655f80ce2aSJacob Faibussowitsch     CHKERRQ(ISEqual(DirichletBoundaries,pcbddc->DirichletBoundariesLocal,&isequal));
76656282151SStefano Zampini   }
767a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
7685f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&pcbddc->DirichletBoundariesLocal));
7695f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
7880f202f7eSStefano Zampini .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);
7965f80ce2aSJacob Faibussowitsch   CHKERRQ(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;
8065f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference((PetscObject)NeumannBoundaries));
80756282151SStefano Zampini   if (pcbddc->NeumannBoundaries) {
8085f80ce2aSJacob Faibussowitsch     CHKERRQ(ISEqual(NeumannBoundaries,pcbddc->NeumannBoundaries,&isequal));
80956282151SStefano Zampini   }
810a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
8115f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&pcbddc->NeumannBoundariesLocal));
8125f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
8320f202f7eSStefano Zampini .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);
8405f80ce2aSJacob Faibussowitsch   CHKERRQ(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;
8505f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference((PetscObject)NeumannBoundaries));
85156282151SStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
8525f80ce2aSJacob Faibussowitsch     CHKERRQ(ISEqual(NeumannBoundaries,pcbddc->NeumannBoundariesLocal,&isequal));
85356282151SStefano Zampini   }
854a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
8555f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&pcbddc->NeumannBoundariesLocal));
8565f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
8750f202f7eSStefano Zampini .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);
8835f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
912785d1243SStefano Zampini .seealso: PCBDDC
913785d1243SStefano Zampini @*/
914785d1243SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
915785d1243SStefano Zampini {
916785d1243SStefano Zampini   PetscFunctionBegin;
917785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
9185f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
948da1bb401SStefano Zampini .seealso: PCBDDC
949da1bb401SStefano Zampini @*/
95082ba6b80SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc,IS *DirichletBoundaries)
951da1bb401SStefano Zampini {
952da1bb401SStefano Zampini   PetscFunctionBegin;
953da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
9545f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
983785d1243SStefano Zampini .seealso: PCBDDC
984785d1243SStefano Zampini @*/
985785d1243SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
986785d1243SStefano Zampini {
987785d1243SStefano Zampini   PetscFunctionBegin;
988785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
9895f80ce2aSJacob Faibussowitsch   CHKERRQ(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 
101953cdbc3dSStefano Zampini .seealso: PCBDDC
102053cdbc3dSStefano Zampini @*/
102182ba6b80SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc,IS *NeumannBoundaries)
102253cdbc3dSStefano Zampini {
102353cdbc3dSStefano Zampini   PetscFunctionBegin;
102453cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
10255f80ce2aSJacob Faibussowitsch   CHKERRQ(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) {
10385f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(xadj));
10395f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(adjncy));
104004194a47SStefano Zampini     }
10415f80ce2aSJacob Faibussowitsch     CHKERRQ(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]) {
10475f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArraycmp(xadj,mat_graph->xadj,nvtxs+1,&same_data));
10482d505d7fSStefano Zampini       if (same_data) {
10495f80ce2aSJacob Faibussowitsch         CHKERRQ(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 */
10555f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCGraphResetCSR(mat_graph));
1056674ae819SStefano Zampini     /* get CSR into graph structure */
1057da1bb401SStefano Zampini     if (copymode == PETSC_COPY_VALUES) {
10585f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(nvtxs+1,&mat_graph->xadj));
10595f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(xadj[nvtxs],&mat_graph->adjncy));
10605f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArraycpy(mat_graph->xadj,xadj,nvtxs+1));
10615f80ce2aSJacob Faibussowitsch       CHKERRQ(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;
107198921bdaSJacob 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 
109428509bceSStefano Zampini .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   }
11065f80ce2aSJacob Faibussowitsch   CHKERRQ(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 */
11085f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f));
1109575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
11105f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(xadj));
11115f80ce2aSJacob Faibussowitsch     CHKERRQ(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;
11265f80ce2aSJacob Faibussowitsch       CHKERRQ(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++) {
11325f80ce2aSJacob Faibussowitsch     CHKERRQ(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++) {
11365f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&pcbddc->ISForDofsLocal[i]));
113763602bcaSStefano Zampini   }
11385f80ce2aSJacob Faibussowitsch   CHKERRQ(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++) {
11415f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&pcbddc->ISForDofs[i]));
114263602bcaSStefano Zampini   }
11435f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(pcbddc->ISForDofs));
114463602bcaSStefano Zampini   pcbddc->n_ISForDofs = 0;
114563602bcaSStefano Zampini   /* allocate space then set */
1146d02579f5SStefano Zampini   if (n_is) {
11475f80ce2aSJacob Faibussowitsch     CHKERRQ(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 
117363602bcaSStefano Zampini .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   }
11865f80ce2aSJacob Faibussowitsch   CHKERRQ(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;
12005f80ce2aSJacob Faibussowitsch       CHKERRQ(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++) {
12065f80ce2aSJacob Faibussowitsch     CHKERRQ(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++) {
12105f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&pcbddc->ISForDofs[i]));
12119c0446d6SStefano Zampini   }
12125f80ce2aSJacob Faibussowitsch   CHKERRQ(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++) {
12155f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&pcbddc->ISForDofsLocal[i]));
121663602bcaSStefano Zampini   }
12175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(pcbddc->ISForDofsLocal));
121863602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = 0;
1219da1bb401SStefano Zampini   /* allocate space then set */
1220d02579f5SStefano Zampini   if (n_is) {
12215f80ce2aSJacob Faibussowitsch     CHKERRQ(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 
12479c0446d6SStefano Zampini .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   }
12605f80ce2aSJacob Faibussowitsch   CHKERRQ(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;
12824df7a6bfSStefano Zampini   PetscBool      iscg = PETSC_FALSE, 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) {
12874df7a6bfSStefano Zampini     PetscBool isgroppcg, ispipecg, ispipelcg, ispipecgrr;
12884df7a6bfSStefano Zampini 
12895f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectTypeCompare((PetscObject)ksp,KSPCG,&iscg));
12905f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectTypeCompare((PetscObject)ksp,KSPGROPPCG,&isgroppcg));
12915f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECG,&ispipecg));
12925f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECG,&ispipelcg));
12935f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECGRR,&ispipecgrr));
12944df7a6bfSStefano Zampini     iscg = (PetscBool)(iscg || isgroppcg || ispipecg || ispipelcg || ispipecgrr);
12953bf6e316SStefano Zampini     if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || !iscg || pc->mat != pc->pmat) {
12965f80ce2aSJacob Faibussowitsch       CHKERRQ(PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE));
129785c4d303SStefano Zampini     }
129885c4d303SStefano Zampini   }
12993bf6e316SStefano Zampini   if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || pc->mat != pc->pmat) {
13005f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE));
1301fc17d649SStefano Zampini   }
13021f4df5f7SStefano Zampini 
130385c4d303SStefano Zampini   /* Creates parallel work vectors used in presolve */
130462a6ff1dSStefano Zampini   if (!pcbddc->original_rhs) {
13055f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs));
130662a6ff1dSStefano Zampini   }
130762a6ff1dSStefano Zampini   if (!pcbddc->temp_solution) {
13085f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution));
130962a6ff1dSStefano Zampini   }
13108d00608fSStefano Zampini 
131127b6a85dSStefano Zampini   pcbddc->temp_solution_used = PETSC_FALSE;
13123972b0daSStefano Zampini   if (x) {
13135f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectReference((PetscObject)x));
13143972b0daSStefano Zampini     used_vec = x;
13158d00608fSStefano Zampini   } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */
13165f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectReference((PetscObject)pcbddc->temp_solution));
13173972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
13185f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSet(used_vec,0.0));
131927b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
13205f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCopy(rhs,pcbddc->original_rhs));
1321266e20e9SStefano Zampini     save_rhs = PETSC_FALSE;
1322266e20e9SStefano Zampini     pcbddc->eliminate_dirdofs = PETSC_TRUE;
13233972b0daSStefano Zampini   }
13248efcfb23SStefano Zampini 
13258efcfb23SStefano Zampini   /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */
13263972b0daSStefano Zampini   if (ksp) {
1327a0cb1b98SStefano Zampini     /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */
13285f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPGetInitialGuessNonzero(ksp,&pcbddc->ksp_guess_nonzero));
13298efcfb23SStefano Zampini     if (!pcbddc->ksp_guess_nonzero) {
13305f80ce2aSJacob Faibussowitsch       CHKERRQ(VecSet(used_vec,0.0));
13313972b0daSStefano Zampini     }
13323972b0daSStefano Zampini   }
13333308cffdSStefano Zampini 
13348d00608fSStefano Zampini   pcbddc->rhs_change = PETSC_FALSE;
13353972b0daSStefano Zampini   /* Take into account zeroed rows -> change rhs and store solution removed */
133670c64980SStefano Zampini   if (rhs && pcbddc->eliminate_dirdofs) {
13373975b054SStefano Zampini     IS dirIS = NULL;
13383975b054SStefano Zampini 
1339a07ea27aSStefano Zampini     /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */
13405f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS));
13413975b054SStefano Zampini     if (dirIS) {
1342906d46d4SStefano Zampini       Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
1343785d1243SStefano Zampini       PetscInt          dirsize,i,*is_indices;
13442b095fd8SStefano Zampini       PetscScalar       *array_x;
13452b095fd8SStefano Zampini       const PetscScalar *array_diagonal;
1346785d1243SStefano Zampini 
13475f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetDiagonal(pc->pmat,pcis->vec1_global));
13485f80ce2aSJacob Faibussowitsch       CHKERRQ(VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global));
13495f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD));
13505f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD));
13515f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterBegin(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD));
13525f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterEnd(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD));
13535f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetLocalSize(dirIS,&dirsize));
13545f80ce2aSJacob Faibussowitsch       CHKERRQ(VecGetArray(pcis->vec1_N,&array_x));
13555f80ce2aSJacob Faibussowitsch       CHKERRQ(VecGetArrayRead(pcis->vec2_N,&array_diagonal));
13565f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetIndices(dirIS,(const PetscInt**)&is_indices));
13572fa5cd67SKarl Rupp       for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
13585f80ce2aSJacob Faibussowitsch       CHKERRQ(ISRestoreIndices(dirIS,(const PetscInt**)&is_indices));
13595f80ce2aSJacob Faibussowitsch       CHKERRQ(VecRestoreArrayRead(pcis->vec2_N,&array_diagonal));
13605f80ce2aSJacob Faibussowitsch       CHKERRQ(VecRestoreArray(pcis->vec1_N,&array_x));
13615f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterBegin(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE));
13625f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterEnd(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE));
13638d00608fSStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
13645f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&dirIS));
13658efcfb23SStefano Zampini     }
1366a07ea27aSStefano Zampini   }
1367b76ba322SStefano Zampini 
13688efcfb23SStefano Zampini   /* remove the computed solution or the initial guess from the rhs */
13698d00608fSStefano Zampini   if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero)) {
137027b6a85dSStefano Zampini     /* save the original rhs */
137127b6a85dSStefano Zampini     if (save_rhs) {
13725f80ce2aSJacob Faibussowitsch       CHKERRQ(VecSwap(rhs,pcbddc->original_rhs));
137327b6a85dSStefano Zampini       save_rhs = PETSC_FALSE;
13748d00608fSStefano Zampini     }
13758d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
13765f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScale(used_vec,-1.0));
13775f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMultAdd(pc->mat,used_vec,pcbddc->original_rhs,rhs));
13785f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScale(used_vec,-1.0));
13795f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCopy(used_vec,pcbddc->temp_solution));
138027b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
13817acc28cbSStefano Zampini     if (ksp) {
13825f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPSetInitialGuessNonzero(ksp,PETSC_FALSE));
13837acc28cbSStefano Zampini     }
13843308cffdSStefano Zampini   }
13855f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&used_vec));
1386b76ba322SStefano Zampini 
1387fc17d649SStefano Zampini   /* compute initial vector in benign space if needed
138827b6a85dSStefano Zampini      and remove non-benign solution from the rhs */
138927b6a85dSStefano Zampini   benign_correction_computed = PETSC_FALSE;
139008af2428SStefano Zampini   if (rhs && pcbddc->benign_compute_correction && (pcbddc->benign_have_null || pcbddc->benign_apply_coarse_only)) {
13911f4df5f7SStefano Zampini     /* compute u^*_h using ideas similar to those in Xuemin Tu's PhD thesis (see Section 4.8.1)
13921f4df5f7SStefano Zampini        Recursively apply BDDC in the multilevel case */
13930369aaf7SStefano Zampini     if (!pcbddc->benign_vec) {
13945f80ce2aSJacob Faibussowitsch       CHKERRQ(VecDuplicate(rhs,&pcbddc->benign_vec));
13950369aaf7SStefano Zampini     }
1396c69e9cc1SStefano Zampini     /* keep applying coarse solver unless we no longer have benign subdomains */
1397c69e9cc1SStefano Zampini     pcbddc->benign_apply_coarse_only = pcbddc->benign_have_null ? PETSC_TRUE : PETSC_FALSE;
139827b6a85dSStefano Zampini     if (!pcbddc->benign_skip_correction) {
13995f80ce2aSJacob Faibussowitsch       CHKERRQ(PCApply_BDDC(pc,rhs,pcbddc->benign_vec));
14003bca92a6SStefano Zampini       benign_correction_computed = PETSC_TRUE;
14011f4df5f7SStefano Zampini       if (pcbddc->temp_solution_used) {
14025f80ce2aSJacob Faibussowitsch         CHKERRQ(VecAXPY(pcbddc->temp_solution,1.0,pcbddc->benign_vec));
14031f4df5f7SStefano Zampini       }
14045f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScale(pcbddc->benign_vec,-1.0));
140527b6a85dSStefano Zampini       /* store the original rhs if not done earlier */
140627b6a85dSStefano Zampini       if (save_rhs) {
14075f80ce2aSJacob Faibussowitsch         CHKERRQ(VecSwap(rhs,pcbddc->original_rhs));
140892e3dcfbSStefano Zampini       }
140927b6a85dSStefano Zampini       if (pcbddc->rhs_change) {
14105f80ce2aSJacob Faibussowitsch         CHKERRQ(MatMultAdd(pc->mat,pcbddc->benign_vec,rhs,rhs));
141127b6a85dSStefano Zampini       } else {
14125f80ce2aSJacob Faibussowitsch         CHKERRQ(MatMultAdd(pc->mat,pcbddc->benign_vec,pcbddc->original_rhs,rhs));
141327b6a85dSStefano Zampini       }
14140369aaf7SStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
141527b6a85dSStefano Zampini     }
141627b6a85dSStefano Zampini     pcbddc->benign_apply_coarse_only = PETSC_FALSE;
14174df7a6bfSStefano Zampini   } else {
14185f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDestroy(&pcbddc->benign_vec));
14190369aaf7SStefano Zampini   }
14202d4c4fecSStefano Zampini 
14212d4c4fecSStefano Zampini   /* dbg output */
1422a198735bSStefano Zampini   if (pcbddc->dbg_flag && benign_correction_computed) {
14231f4df5f7SStefano Zampini     Vec v;
1424c69e9cc1SStefano Zampini 
14255f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDuplicate(pcis->vec1_global,&v));
1426c69e9cc1SStefano Zampini     if (pcbddc->ChangeOfBasisMatrix) {
14275f80ce2aSJacob Faibussowitsch       CHKERRQ(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,v));
1428c69e9cc1SStefano Zampini     } else {
14295f80ce2aSJacob Faibussowitsch       CHKERRQ(VecCopy(rhs,v));
1430c69e9cc1SStefano Zampini     }
14315f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCBenignGetOrSetP0(pc,v,PETSC_TRUE));
14325f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"LEVEL %D: is the correction benign?\n",pcbddc->current_level));
14335f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscScalarView(pcbddc->benign_n,pcbddc->benign_p0,pcbddc->dbg_viewer));
14345f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerFlush(pcbddc->dbg_viewer));
14355f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDestroy(&v));
14361f4df5f7SStefano Zampini   }
14370369aaf7SStefano Zampini 
14380369aaf7SStefano Zampini   /* set initial guess if using PCG */
14398ae0ca82SStefano Zampini   pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
14400369aaf7SStefano Zampini   if (x && pcbddc->use_exact_dirichlet_trick) {
14415f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSet(x,0.0));
14421dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
144327b6a85dSStefano Zampini       if (benign_correction_computed) { /* we have already saved the changed rhs */
14445f80ce2aSJacob Faibussowitsch         CHKERRQ(VecLockReadPop(pcis->vec1_global));
14451dd7afcfSStefano Zampini       } else {
14465f80ce2aSJacob Faibussowitsch         CHKERRQ(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,pcis->vec1_global));
14471dd7afcfSStefano Zampini       }
14485f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterBegin(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
14495f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterEnd(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
14501dd7afcfSStefano Zampini     } else {
14515f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
14525f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterEnd(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
14531dd7afcfSStefano Zampini     }
14545f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
14555f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D));
14565f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
14575f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D));
14581dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
14595f80ce2aSJacob Faibussowitsch       CHKERRQ(VecSet(pcis->vec1_global,0.));
14605f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterBegin(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE));
14615f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterEnd(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE));
14625f80ce2aSJacob Faibussowitsch       CHKERRQ(MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x));
14631dd7afcfSStefano Zampini     } else {
14645f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterBegin(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE));
14655f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterEnd(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE));
14661dd7afcfSStefano Zampini     }
14670369aaf7SStefano Zampini     if (ksp) {
14685f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPSetInitialGuessNonzero(ksp,PETSC_TRUE));
14690369aaf7SStefano Zampini     }
14708ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_TRUE;
1471266e20e9SStefano Zampini   } else if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior && benign_correction_computed && pcbddc->use_exact_dirichlet_trick) {
14725f80ce2aSJacob Faibussowitsch     CHKERRQ(VecLockReadPop(pcis->vec1_global));
14730369aaf7SStefano Zampini   }
1474534831adSStefano Zampini   PetscFunctionReturn(0);
1475534831adSStefano Zampini }
1476906d46d4SStefano Zampini 
1477534831adSStefano Zampini /*
1478534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
1479534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
1480534831adSStefano Zampini 
1481534831adSStefano Zampini    Input Parameter:
1482966d8056SPierre Jolivet +  pc - the preconditioner context
1483534831adSStefano Zampini 
1484534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
1485534831adSStefano Zampini 
1486534831adSStefano Zampini    Notes:
1487534831adSStefano Zampini      The interface routine PCPostSolve() is not usually called directly by
1488534831adSStefano Zampini      the user, but instead is called by KSPSolve().
1489534831adSStefano Zampini */
1490534831adSStefano Zampini static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1491534831adSStefano Zampini {
1492534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1493534831adSStefano Zampini 
1494534831adSStefano Zampini   PetscFunctionBegin;
14953972b0daSStefano Zampini   /* add solution removed in presolve */
14966bcfc461SStefano Zampini   if (x && pcbddc->rhs_change) {
149727b6a85dSStefano Zampini     if (pcbddc->temp_solution_used) {
14985f80ce2aSJacob Faibussowitsch       CHKERRQ(VecAXPY(x,1.0,pcbddc->temp_solution));
1499af140850Sstefano_zampini     } else if (pcbddc->benign_compute_correction && pcbddc->benign_vec) {
15005f80ce2aSJacob Faibussowitsch       CHKERRQ(VecAXPY(x,-1.0,pcbddc->benign_vec));
15013425bc38SStefano Zampini     }
1502af140850Sstefano_zampini     /* restore to original state (not for FETI-DP) */
1503af140850Sstefano_zampini     if (ksp) pcbddc->temp_solution_used = PETSC_FALSE;
150427b6a85dSStefano Zampini   }
150527b6a85dSStefano Zampini 
1506266e20e9SStefano Zampini   /* restore rhs to its original state (not needed for FETI-DP) */
15078d00608fSStefano Zampini   if (rhs && pcbddc->rhs_change) {
15085f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSwap(rhs,pcbddc->original_rhs));
15098d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_FALSE;
1510af140850Sstefano_zampini   }
15118efcfb23SStefano Zampini   /* restore ksp guess state */
15128efcfb23SStefano Zampini   if (ksp) {
15135f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPSetInitialGuessNonzero(ksp,pcbddc->ksp_guess_nonzero));
15148ae0ca82SStefano Zampini     /* reset flag for exact dirichlet trick */
15158ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
1516af140850Sstefano_zampini   }
1517534831adSStefano Zampini   PetscFunctionReturn(0);
1518534831adSStefano Zampini }
1519af140850Sstefano_zampini 
15200c7d97c5SJed Brown /*
15210c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
15220c7d97c5SJed Brown                   by setting data structures and options.
15230c7d97c5SJed Brown 
15240c7d97c5SJed Brown    Input Parameter:
152553cdbc3dSStefano Zampini +  pc - the preconditioner context
15260c7d97c5SJed Brown 
15270c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
15280c7d97c5SJed Brown 
15290c7d97c5SJed Brown    Notes:
15300c7d97c5SJed Brown      The interface routine PCSetUp() is not usually called directly by
15310c7d97c5SJed Brown      the user, but instead is called by PCApply() if necessary.
15320c7d97c5SJed Brown */
153353cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
15340c7d97c5SJed Brown {
15350c7d97c5SJed Brown   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1536c703fcc7SStefano Zampini   PCBDDCSubSchurs sub_schurs;
15375e8657edSStefano Zampini   Mat_IS*         matis;
153808122e43SStefano Zampini   MatNullSpace    nearnullspace;
153935509ce9Sstefano_zampini   Mat             lA;
154035509ce9Sstefano_zampini   IS              lP,zerodiag = NULL;
154191e8d312SStefano Zampini   PetscInt        nrows,ncols;
154286bfa4cfSStefano Zampini   PetscMPIInt     size;
1543c703fcc7SStefano Zampini   PetscBool       computesubschurs;
15448de1fae6SStefano Zampini   PetscBool       computeconstraintsmatrix;
15453b03f7bbSStefano Zampini   PetscBool       new_nearnullspace_provided,ismatis,rl;
15460c7d97c5SJed Brown 
15470c7d97c5SJed Brown   PetscFunctionBegin;
15485f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)pc->pmat,MATIS,&ismatis));
1549*28b400f6SJacob Faibussowitsch   PetscCheck(ismatis,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner requires matrix of type MATIS");
15505f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(pc->pmat,&nrows,&ncols));
15512c71b3e2SJacob Faibussowitsch   PetscCheckFalse(nrows != ncols,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCBDDC preconditioner requires a square preconditioning matrix");
15525f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size));
155386bfa4cfSStefano Zampini 
15545e8657edSStefano Zampini   matis = (Mat_IS*)pc->pmat->data;
1555f4ddd8eeSStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */
15563b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
155771582508SStefano Zampini      Also, BDDC builds its own KSP for the Dirichlet problem */
15583b03f7bbSStefano Zampini   rl = pcbddc->recompute_topography;
15593b03f7bbSStefano Zampini   if (!pc->setupcalled || pc->flag == DIFFERENT_NONZERO_PATTERN) rl = PETSC_TRUE;
15605f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPIU_Allreduce(&rl,&pcbddc->recompute_topography,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc)));
1561c83e1ba7SStefano Zampini   if (pcbddc->recompute_topography) {
1562c83e1ba7SStefano Zampini     pcbddc->graphanalyzed    = PETSC_FALSE;
1563c83e1ba7SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1564c83e1ba7SStefano Zampini   } else {
15658de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_FALSE;
1566c83e1ba7SStefano Zampini   }
1567b087196eSStefano Zampini 
1568b087196eSStefano Zampini   /* check parameters' compatibility */
1569b7ab4a40SStefano Zampini   if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE;
1570bd2a564bSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_threshold[0] != 0.0 || pcbddc->adaptive_threshold[1] != 0.0);
157186bfa4cfSStefano Zampini   pcbddc->use_deluxe_scaling   = (PetscBool)(pcbddc->use_deluxe_scaling && size > 1);
157286bfa4cfSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_selection && size > 1);
1573bf3a8328SStefano Zampini   pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined);
1574862806e4SStefano Zampini   if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE;
1575862806e4SStefano Zampini 
15765a95e1ceSStefano Zampini   computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling);
157716909a7fSStefano Zampini 
157871582508SStefano Zampini   /* activate all connected components if the netflux has been requested */
1579bb05f991SStefano Zampini   if (pcbddc->compute_nonetflux) {
1580bb05f991SStefano Zampini     pcbddc->use_vertices = PETSC_TRUE;
1581bb05f991SStefano Zampini     pcbddc->use_edges    = PETSC_TRUE;
1582bb05f991SStefano Zampini     pcbddc->use_faces    = PETSC_TRUE;
1583bb05f991SStefano Zampini   }
1584bb05f991SStefano Zampini 
1585f4ddd8eeSStefano Zampini   /* Get stdout for dbg */
158670cf5478SStefano Zampini   if (pcbddc->dbg_flag) {
158770cf5478SStefano Zampini     if (!pcbddc->dbg_viewer) {
158858a03d70SStefano Zampini       pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc));
1589f4ddd8eeSStefano Zampini     }
15905f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer));
15915f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2*pcbddc->current_level));
1592f4ddd8eeSStefano Zampini   }
1593f4ddd8eeSStefano Zampini 
1594c703fcc7SStefano Zampini   /* process topology information */
15955f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(PC_BDDC_Topology[pcbddc->current_level],pc,0,0,0));
159671582508SStefano Zampini   if (pcbddc->recompute_topography) {
15975f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCComputeLocalTopologyInfo(pc));
1598c703fcc7SStefano Zampini     if (pcbddc->discretegradient) {
15995f80ce2aSJacob Faibussowitsch       CHKERRQ(PCBDDCNedelecSupport(pc));
1600a13144ffSStefano Zampini     }
1601c703fcc7SStefano Zampini   }
16024f819b78SStefano Zampini   if (pcbddc->corner_selected) pcbddc->use_vertices = PETSC_TRUE;
1603a13144ffSStefano Zampini 
1604c703fcc7SStefano Zampini   /* change basis if requested by the user */
16055e8657edSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) {
16065e8657edSStefano Zampini     /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */
16075e8657edSStefano Zampini     pcbddc->use_change_of_basis = PETSC_FALSE;
16085f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCComputeLocalMatrix(pc,pcbddc->user_ChangeOfBasisMatrix));
16095e8657edSStefano Zampini   } else {
16105f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&pcbddc->local_mat));
16115f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectReference((PetscObject)matis->A));
16125e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
1613d16cbb6bSStefano Zampini   }
1614d16cbb6bSStefano Zampini 
16154f1b2e48SStefano Zampini   /*
1616c703fcc7SStefano Zampini      Compute change of basis on local pressures (aka zerodiag dofs) with the benign trick
16174f1b2e48SStefano Zampini      This should come earlier then PCISSetUp for extracting the correct subdomain matrices
16184f1b2e48SStefano Zampini   */
16195f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCBenignShellMat(pc,PETSC_TRUE));
1620d16cbb6bSStefano Zampini   if (pcbddc->benign_saddle_point) {
16219f47a83aSStefano Zampini     PC_IS* pcis = (PC_IS*)pc->data;
16229f47a83aSStefano Zampini 
162305b28244SStefano Zampini     if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE;
16243b03f7bbSStefano Zampini     /* detect local saddle point and change the basis in pcbddc->local_mat */
16255f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCBenignDetectSaddlePoint(pc,(PetscBool)(!pcbddc->recompute_topography),&zerodiag));
1626a3df083aSStefano Zampini     /* pop B0 mat from local mat */
16275f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE));
16281dd7afcfSStefano Zampini     /* give pcis a hint to not reuse submatrices during PCISCreate */
16291dd7afcfSStefano Zampini     if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) {
16301dd7afcfSStefano Zampini       if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) {
16311dd7afcfSStefano Zampini         pcis->reusesubmatrices = PETSC_FALSE;
16321dd7afcfSStefano Zampini       } else {
1633a3df083aSStefano Zampini         pcis->reusesubmatrices = PETSC_TRUE;
16341dd7afcfSStefano Zampini       }
1635a3df083aSStefano Zampini     } else {
16369f47a83aSStefano Zampini       pcis->reusesubmatrices = PETSC_FALSE;
1637674ae819SStefano Zampini     }
1638a3df083aSStefano Zampini   }
163927b6a85dSStefano Zampini 
16408037d520SStefano Zampini   /* propagate relevant information */
164106a4e24aSStefano Zampini   if (matis->A->symmetric_set) {
16425f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric));
164306a4e24aSStefano Zampini   }
164406a4e24aSStefano Zampini   if (matis->A->spd_set) {
16455f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetOption(pcbddc->local_mat,MAT_SPD,matis->A->spd));
164606a4e24aSStefano Zampini   }
1647e496cd5dSStefano Zampini 
16485e8657edSStefano Zampini   /* Set up all the "iterative substructuring" common block without computing solvers */
16495e8657edSStefano Zampini   {
16505e8657edSStefano Zampini     Mat temp_mat;
16515e8657edSStefano Zampini 
16525e8657edSStefano Zampini     temp_mat = matis->A;
16535e8657edSStefano Zampini     matis->A = pcbddc->local_mat;
16545f80ce2aSJacob Faibussowitsch     CHKERRQ(PCISSetUp(pc,PETSC_TRUE,PETSC_FALSE));
16555e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
16565e8657edSStefano Zampini     matis->A = temp_mat;
16575e8657edSStefano Zampini   }
1658684f6988SStefano Zampini 
165981d14e9dSStefano Zampini   /* Analyze interface */
166064ac59b8SStefano Zampini   if (!pcbddc->graphanalyzed) {
16615f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCAnalyzeInterface(pc));
16628de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1663345ecf6cSStefano Zampini     if (pcbddc->adaptive_selection && !pcbddc->use_deluxe_scaling && !pcbddc->mat_graph->twodim) {
16644247aa23Sstefano_zampini       SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot compute the adaptive primal space for a problem with 3D edges without deluxe scaling");
1665345ecf6cSStefano Zampini     }
1666a198735bSStefano Zampini     if (pcbddc->compute_nonetflux) {
1667669cc0f4SStefano Zampini       MatNullSpace nnfnnsp;
1668669cc0f4SStefano Zampini 
1669*28b400f6SJacob Faibussowitsch       PetscCheck(pcbddc->divudotp,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Missing divudotp operator");
16705f80ce2aSJacob Faibussowitsch       CHKERRQ(PCBDDCComputeNoNetFlux(pc->pmat,pcbddc->divudotp,pcbddc->divudotp_trans,pcbddc->divudotp_vl2l,pcbddc->mat_graph,&nnfnnsp));
167171582508SStefano Zampini       /* TODO what if a nearnullspace is already attached? */
16728037d520SStefano Zampini       if (nnfnnsp) {
16735f80ce2aSJacob Faibussowitsch         CHKERRQ(MatSetNearNullSpace(pc->pmat,nnfnnsp));
16745f80ce2aSJacob Faibussowitsch         CHKERRQ(MatNullSpaceDestroy(&nnfnnsp));
1675669cc0f4SStefano Zampini       }
1676674ae819SStefano Zampini     }
16778037d520SStefano Zampini   }
16785f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(PC_BDDC_Topology[pcbddc->current_level],pc,0,0,0));
1679fb8d54d4SStefano Zampini 
16805408967cSStefano Zampini   /* check existence of a divergence free extension, i.e.
16815408967cSStefano Zampini      b(v_I,p_0) = 0 for all v_I (raise error if not).
16825408967cSStefano Zampini      Also, check that PCBDDCBenignGetOrSetP0 works */
1683ff1f7e73Sstefano_zampini   if (pcbddc->benign_saddle_point && pcbddc->dbg_flag > 1) {
16845f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCBenignCheck(pc,zerodiag));
168509f581a4SStefano Zampini   }
16865f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&zerodiag));
168706f24817SStefano Zampini 
1688b96c3477SStefano Zampini   /* Setup local dirichlet solver ksp_D and sub_schurs solvers */
1689c703fcc7SStefano Zampini   if (computesubschurs && pcbddc->recompute_topography) {
16905f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCInitSubSchurs(pc));
1691b1b3d7a2SStefano Zampini   }
16929d54b7f4SStefano Zampini   /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/
16939d54b7f4SStefano Zampini   if (!pcbddc->use_deluxe_scaling) {
16945f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCScalingSetUp(pc));
16959d54b7f4SStefano Zampini   }
1696c703fcc7SStefano Zampini 
1697c703fcc7SStefano Zampini   /* finish setup solvers and do adaptive selection of constraints */
1698b334f244SStefano Zampini   sub_schurs = pcbddc->sub_schurs;
1699b334f244SStefano Zampini   if (sub_schurs && sub_schurs->schur_explicit) {
17002070dbb6SStefano Zampini     if (computesubschurs) {
17015f80ce2aSJacob Faibussowitsch       CHKERRQ(PCBDDCSetUpSubSchurs(pc));
17022070dbb6SStefano Zampini     }
17035f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE));
1704d5574798SStefano Zampini   } else {
17055f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE));
17062070dbb6SStefano Zampini     if (computesubschurs) {
17075f80ce2aSJacob Faibussowitsch       CHKERRQ(PCBDDCSetUpSubSchurs(pc));
1708d5574798SStefano Zampini     }
17092070dbb6SStefano Zampini   }
171008122e43SStefano Zampini   if (pcbddc->adaptive_selection) {
17115f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCAdaptiveSelection(pc));
17128de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1713b7eb3628SStefano Zampini   }
1714684f6988SStefano Zampini 
1715f4ddd8eeSStefano Zampini   /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */
1716fb8d54d4SStefano Zampini   new_nearnullspace_provided = PETSC_FALSE;
17175f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetNearNullSpace(pc->pmat,&nearnullspace));
1718f4ddd8eeSStefano Zampini   if (pcbddc->onearnullspace) { /* already used nearnullspace */
1719f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* near null space attached to mat has been destroyed */
1720f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1721f4ddd8eeSStefano Zampini     } else {
1722f4ddd8eeSStefano Zampini       /* determine if the two nullspaces are different (should be lightweight) */
1723f4ddd8eeSStefano Zampini       if (nearnullspace != pcbddc->onearnullspace) {
1724f4ddd8eeSStefano Zampini         new_nearnullspace_provided = PETSC_TRUE;
1725165b64e2SStefano Zampini       } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */
1726f4ddd8eeSStefano Zampini         PetscInt         i;
1727165b64e2SStefano Zampini         const Vec        *nearnullvecs;
1728165b64e2SStefano Zampini         PetscObjectState state;
1729165b64e2SStefano Zampini         PetscInt         nnsp_size;
17305f80ce2aSJacob Faibussowitsch         CHKERRQ(MatNullSpaceGetVecs(nearnullspace,NULL,&nnsp_size,&nearnullvecs));
1731f4ddd8eeSStefano Zampini         for (i=0;i<nnsp_size;i++) {
17325f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscObjectStateGet((PetscObject)nearnullvecs[i],&state));
1733165b64e2SStefano Zampini           if (pcbddc->onearnullvecs_state[i] != state) {
1734f4ddd8eeSStefano Zampini             new_nearnullspace_provided = PETSC_TRUE;
1735f4ddd8eeSStefano Zampini             break;
1736f4ddd8eeSStefano Zampini           }
1737f4ddd8eeSStefano Zampini         }
1738f4ddd8eeSStefano Zampini       }
1739f4ddd8eeSStefano Zampini     }
1740f4ddd8eeSStefano Zampini   } else {
1741f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* both nearnullspaces are null */
1742f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_FALSE;
1743f4ddd8eeSStefano Zampini     } else { /* nearnullspace attached later */
1744f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1745f4ddd8eeSStefano Zampini     }
1746f4ddd8eeSStefano Zampini   }
1747f4ddd8eeSStefano Zampini 
1748f4ddd8eeSStefano Zampini   /* Setup constraints and related work vectors */
1749727cdba6SStefano Zampini   /* reset primal space flags */
17505f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(PC_BDDC_LocalWork[pcbddc->current_level],pc,0,0,0));
1751f4ddd8eeSStefano Zampini   pcbddc->new_primal_space = PETSC_FALSE;
1752727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_FALSE;
17538de1fae6SStefano Zampini   if (computeconstraintsmatrix || new_nearnullspace_provided) {
1754727cdba6SStefano Zampini     /* It also sets the primal space flags */
17555f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCConstraintsSetUp(pc));
17569543d0ffSStefano Zampini   }
1757e7b262bdSStefano Zampini   /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */
17585f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCSetUpLocalWorkVectors(pc));
17595e8657edSStefano Zampini 
17605e8657edSStefano Zampini   if (pcbddc->use_change_of_basis) {
17615e8657edSStefano Zampini     PC_IS *pcis = (PC_IS*)(pc->data);
17625e8657edSStefano Zampini 
17635f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCComputeLocalMatrix(pc,pcbddc->ChangeOfBasisMatrix));
17644f1b2e48SStefano Zampini     if (pcbddc->benign_change) {
17655f80ce2aSJacob Faibussowitsch       CHKERRQ(MatDestroy(&pcbddc->benign_B0));
1766c263805aSStefano Zampini       /* pop B0 from pcbddc->local_mat */
17675f80ce2aSJacob Faibussowitsch       CHKERRQ(PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE));
1768c263805aSStefano Zampini     }
17695e8657edSStefano Zampini     /* get submatrices */
17705f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&pcis->A_IB));
17715f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&pcis->A_BI));
17725f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&pcis->A_BB));
17735f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB));
17745f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreateSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB));
17755f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI));
17763975b054SStefano Zampini     /* set flag in pcis to not reuse submatrices during PCISCreate */
17773975b054SStefano Zampini     pcis->reusesubmatrices = PETSC_FALSE;
17789c6a02ceSStefano Zampini   } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) {
17795f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&pcbddc->local_mat));
17805f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectReference((PetscObject)matis->A));
17815e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
17825e8657edSStefano Zampini   }
178335509ce9Sstefano_zampini 
178435509ce9Sstefano_zampini   /* interface pressure block row for B_C */
17855f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP" ,(PetscObject*)&lP));
17865f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA));
178735509ce9Sstefano_zampini   if (lA && lP) {
178835509ce9Sstefano_zampini     PC_IS*    pcis = (PC_IS*)pc->data;
178935509ce9Sstefano_zampini     Mat       B_BI,B_BB,Bt_BI,Bt_BB;
179035509ce9Sstefano_zampini     PetscBool issym;
17915f80ce2aSJacob Faibussowitsch     CHKERRQ(MatIsSymmetric(lA,PETSC_SMALL,&issym));
17926cc1294bSstefano_zampini     if (issym) {
17935f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI));
17945f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB));
17955f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreateTranspose(B_BI,&Bt_BI));
17965f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreateTranspose(B_BB,&Bt_BB));
179735509ce9Sstefano_zampini     } else {
17985f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI));
17995f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB));
18005f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreateSubMatrix(lA,pcis->is_I_local,lP,MAT_INITIAL_MATRIX,&Bt_BI));
18015f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreateSubMatrix(lA,pcis->is_B_local,lP,MAT_INITIAL_MATRIX,&Bt_BB));
180235509ce9Sstefano_zampini     }
18035f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BI",(PetscObject)B_BI));
18045f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BB",(PetscObject)B_BB));
18055f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BI",(PetscObject)Bt_BI));
18065f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BB",(PetscObject)Bt_BB));
18075f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&B_BI));
18085f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&B_BB));
18095f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&Bt_BI));
18105f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&Bt_BB));
181135509ce9Sstefano_zampini   }
18125f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(PC_BDDC_LocalWork[pcbddc->current_level],pc,0,0,0));
181335509ce9Sstefano_zampini 
1814b96c3477SStefano Zampini   /* SetUp coarse and local Neumann solvers */
18155f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCSetUpSolvers(pc));
1816b96c3477SStefano Zampini   /* SetUp Scaling operator */
18179d54b7f4SStefano Zampini   if (pcbddc->use_deluxe_scaling) {
18185f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCScalingSetUp(pc));
18190c7d97c5SJed Brown   }
1820c703fcc7SStefano Zampini 
18211dd7afcfSStefano Zampini   /* mark topography as done */
182256282151SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
18230369aaf7SStefano Zampini 
18241dd7afcfSStefano Zampini   /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */
18255f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCBenignShellMat(pc,PETSC_FALSE));
18261dd7afcfSStefano Zampini 
182758a03d70SStefano Zampini   if (pcbddc->dbg_flag) {
18285f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2*pcbddc->current_level));
18295f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer));
18302b510759SStefano Zampini   }
18310c7d97c5SJed Brown   PetscFunctionReturn(0);
18320c7d97c5SJed Brown }
18330c7d97c5SJed Brown 
18340c7d97c5SJed Brown /*
183550efa1b5SStefano Zampini    PCApply_BDDC - Applies the BDDC operator to a vector.
18360c7d97c5SJed Brown 
18370c7d97c5SJed Brown    Input Parameters:
18380f202f7eSStefano Zampini +  pc - the preconditioner context
18390f202f7eSStefano Zampini -  r - input vector (global)
18400c7d97c5SJed Brown 
18410c7d97c5SJed Brown    Output Parameter:
18420c7d97c5SJed Brown .  z - output vector (global)
18430c7d97c5SJed Brown 
18440c7d97c5SJed Brown    Application Interface Routine: PCApply()
18450c7d97c5SJed Brown  */
184653cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
18470c7d97c5SJed Brown {
18480c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
18490c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1850b3338236SStefano Zampini   Mat               lA = NULL;
1851b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
18523b03a366Sstefano_zampini   const PetscScalar one = 1.0;
18533b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
18542617d88aSStefano Zampini   const PetscScalar zero = 0.0;
18550c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
18560c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
1857b097fa66SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */
18580c7d97c5SJed Brown 
18590c7d97c5SJed Brown   PetscFunctionBegin;
18605f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCitationsRegister(citation,&cited));
1861b3338236SStefano Zampini   if (pcbddc->switch_static) {
18625f80ce2aSJacob Faibussowitsch     CHKERRQ(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat,&lA));
1863b3338236SStefano Zampini   }
1864b3338236SStefano Zampini 
18651dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
18661dd7afcfSStefano Zampini     Vec swap;
186727b6a85dSStefano Zampini 
18685f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change));
18691dd7afcfSStefano Zampini     swap = pcbddc->work_change;
18701dd7afcfSStefano Zampini     pcbddc->work_change = r;
18711dd7afcfSStefano Zampini     r = swap;
18721dd7afcfSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
18739cc2a9b1Sstefano_zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) {
18745f80ce2aSJacob Faibussowitsch       CHKERRQ(VecCopy(r,pcis->vec1_global));
18755f80ce2aSJacob Faibussowitsch       CHKERRQ(VecLockReadPush(pcis->vec1_global));
18761dd7afcfSStefano Zampini     }
18771dd7afcfSStefano Zampini   }
187827b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
18795f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE));
1880efc2fbd9SStefano Zampini   }
1881bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET && !pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
18825f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCopy(r,z));
18830c7d97c5SJed Brown     /* First Dirichlet solve */
18845f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
18855f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
18860c7d97c5SJed Brown     /*
18870c7d97c5SJed Brown       Assembling right hand side for BDDC operator
1888b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
1889674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
18900c7d97c5SJed Brown     */
1891b097fa66SStefano Zampini     if (n_D) {
18925f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
18935f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D));
18945f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
18955f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D));
18965f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScale(pcis->vec2_D,m_one));
189716909a7fSStefano Zampini       if (pcbddc->switch_static) {
18985f80ce2aSJacob Faibussowitsch         CHKERRQ(VecSet(pcis->vec1_N,0.));
18995f80ce2aSJacob Faibussowitsch         CHKERRQ(VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
19005f80ce2aSJacob Faibussowitsch         CHKERRQ(VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
190116909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
19025f80ce2aSJacob Faibussowitsch           CHKERRQ(MatMult(lA,pcis->vec1_N,pcis->vec2_N));
190316909a7fSStefano Zampini         } else {
19045f80ce2aSJacob Faibussowitsch           CHKERRQ(MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N));
19055f80ce2aSJacob Faibussowitsch           CHKERRQ(MatMult(lA,pcis->vec2_N,pcis->vec1_N));
19065f80ce2aSJacob Faibussowitsch           CHKERRQ(MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N));
190716909a7fSStefano Zampini         }
19085f80ce2aSJacob Faibussowitsch         CHKERRQ(VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD));
19095f80ce2aSJacob Faibussowitsch         CHKERRQ(VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD));
19105f80ce2aSJacob Faibussowitsch         CHKERRQ(VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
19115f80ce2aSJacob Faibussowitsch         CHKERRQ(VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
191216909a7fSStefano Zampini       } else {
19135f80ce2aSJacob Faibussowitsch         CHKERRQ(MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B));
191416909a7fSStefano Zampini       }
1915b097fa66SStefano Zampini     } else {
19165f80ce2aSJacob Faibussowitsch       CHKERRQ(VecSet(pcis->vec1_B,zero));
1917b097fa66SStefano Zampini     }
19185f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE));
19195f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE));
19205f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCScalingRestriction(pc,z,pcis->vec1_B));
1921b76ba322SStefano Zampini   } else {
19224fee134fSStefano Zampini     if (!pcbddc->benign_apply_coarse_only) {
19235f80ce2aSJacob Faibussowitsch       CHKERRQ(PCBDDCScalingRestriction(pc,r,pcis->vec1_B));
1924b76ba322SStefano Zampini     }
19254fee134fSStefano Zampini   }
1926bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) {
1927*28b400f6SJacob Faibussowitsch     PetscCheck(pcbddc->switch_static,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"You forgot to pass -pc_bddc_switch_static");
19285f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
19295f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
1930bc960bbfSJed Brown   }
1931b76ba322SStefano Zampini 
19322617d88aSStefano Zampini   /* Apply interface preconditioner
19332617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
19345f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE));
19352617d88aSStefano Zampini 
1936674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
19375f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCScalingExtension(pc,pcis->vec1_B,z));
1938bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) {
19395f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterBegin(pcis->global_to_D,pcis->vec1_D,z,INSERT_VALUES,SCATTER_REVERSE));
19405f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterEnd(pcis->global_to_D,pcis->vec1_D,z,INSERT_VALUES,SCATTER_REVERSE));
1941bc960bbfSJed Brown     PetscFunctionReturn(0);
1942bc960bbfSJed Brown   }
19433b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
19445f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
19455f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
1946b097fa66SStefano Zampini   if (n_B) {
194716909a7fSStefano Zampini     if (pcbddc->switch_static) {
19485f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
19495f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
19505f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
19515f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
195216909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
19535f80ce2aSJacob Faibussowitsch         CHKERRQ(MatMult(lA,pcis->vec1_N,pcis->vec2_N));
195416909a7fSStefano Zampini       } else {
19555f80ce2aSJacob Faibussowitsch         CHKERRQ(MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N));
19565f80ce2aSJacob Faibussowitsch         CHKERRQ(MatMult(lA,pcis->vec2_N,pcis->vec1_N));
19575f80ce2aSJacob Faibussowitsch         CHKERRQ(MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N));
195816909a7fSStefano Zampini       }
19595f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD));
19605f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD));
196116909a7fSStefano Zampini     } else {
19625f80ce2aSJacob Faibussowitsch       CHKERRQ(MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D));
196316909a7fSStefano Zampini     }
196416909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
196516909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
19665f80ce2aSJacob Faibussowitsch       CHKERRQ(MatMult(lA,pcis->vec1_D,pcis->vec3_D));
196716909a7fSStefano Zampini     } else {
19685f80ce2aSJacob Faibussowitsch       CHKERRQ(MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N));
19695f80ce2aSJacob Faibussowitsch       CHKERRQ(MatMult(lA,pcis->vec1_N,pcis->vec2_N));
19705f80ce2aSJacob Faibussowitsch       CHKERRQ(MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D));
197116909a7fSStefano Zampini     }
1972b097fa66SStefano Zampini   }
19735f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
19745f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D));
19755f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
19765f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec4_D));
1977efc2fbd9SStefano Zampini 
19788ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1979b097fa66SStefano Zampini     if (pcbddc->switch_static) {
19805f80ce2aSJacob Faibussowitsch       CHKERRQ(VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D));
1981b097fa66SStefano Zampini     } else {
19825f80ce2aSJacob Faibussowitsch       CHKERRQ(VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D));
1983b097fa66SStefano Zampini     }
19845f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE));
19855f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE));
1986b097fa66SStefano Zampini   } else {
1987b097fa66SStefano Zampini     if (pcbddc->switch_static) {
19885f80ce2aSJacob Faibussowitsch       CHKERRQ(VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D));
1989b097fa66SStefano Zampini     } else {
19905f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScale(pcis->vec4_D,m_one));
1991b097fa66SStefano Zampini     }
19925f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE));
19935f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE));
1994b097fa66SStefano Zampini   }
199527b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
19961dd7afcfSStefano Zampini     if (pcbddc->benign_apply_coarse_only) {
19975f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n));
19981dd7afcfSStefano Zampini     }
19995f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE));
2000efc2fbd9SStefano Zampini   }
20011f4df5f7SStefano Zampini 
20021dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2003f913dca9SStefano Zampini     pcbddc->work_change = r;
20045f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCopy(z,pcbddc->work_change));
20055f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z));
20061dd7afcfSStefano Zampini   }
20070c7d97c5SJed Brown   PetscFunctionReturn(0);
20080c7d97c5SJed Brown }
200950efa1b5SStefano Zampini 
201050efa1b5SStefano Zampini /*
201150efa1b5SStefano Zampini    PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector.
201250efa1b5SStefano Zampini 
201350efa1b5SStefano Zampini    Input Parameters:
20140f202f7eSStefano Zampini +  pc - the preconditioner context
20150f202f7eSStefano Zampini -  r - input vector (global)
201650efa1b5SStefano Zampini 
201750efa1b5SStefano Zampini    Output Parameter:
201850efa1b5SStefano Zampini .  z - output vector (global)
201950efa1b5SStefano Zampini 
202050efa1b5SStefano Zampini    Application Interface Routine: PCApplyTranspose()
202150efa1b5SStefano Zampini  */
202250efa1b5SStefano Zampini PetscErrorCode PCApplyTranspose_BDDC(PC pc,Vec r,Vec z)
202350efa1b5SStefano Zampini {
202450efa1b5SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
202550efa1b5SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
2026b3338236SStefano Zampini   Mat               lA = NULL;
2027b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
202850efa1b5SStefano Zampini   const PetscScalar one = 1.0;
202950efa1b5SStefano Zampini   const PetscScalar m_one = -1.0;
203050efa1b5SStefano Zampini   const PetscScalar zero = 0.0;
203150efa1b5SStefano Zampini 
203250efa1b5SStefano Zampini   PetscFunctionBegin;
20335f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCitationsRegister(citation,&cited));
2034b3338236SStefano Zampini   if (pcbddc->switch_static) {
20355f80ce2aSJacob Faibussowitsch     CHKERRQ(MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat,&lA));
2036b3338236SStefano Zampini   }
20371dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
20381dd7afcfSStefano Zampini     Vec swap;
203927b6a85dSStefano Zampini 
20405f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change));
20411dd7afcfSStefano Zampini     swap = pcbddc->work_change;
20421dd7afcfSStefano Zampini     pcbddc->work_change = r;
20431dd7afcfSStefano Zampini     r = swap;
204427b6a85dSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
20458ae0ca82SStefano Zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->exact_dirichlet_trick_app && pcbddc->change_interior) {
20465f80ce2aSJacob Faibussowitsch       CHKERRQ(VecCopy(r,pcis->vec1_global));
20475f80ce2aSJacob Faibussowitsch       CHKERRQ(VecLockReadPush(pcis->vec1_global));
20481dd7afcfSStefano Zampini     }
204927b6a85dSStefano Zampini   }
205027b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
20515f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE));
2052537c1cdfSStefano Zampini   }
20538ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
20545f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCopy(r,z));
205550efa1b5SStefano Zampini     /* First Dirichlet solve */
20565f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
20575f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD));
205850efa1b5SStefano Zampini     /*
205950efa1b5SStefano Zampini       Assembling right hand side for BDDC operator
2060b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
206150efa1b5SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
206250efa1b5SStefano Zampini     */
2063b097fa66SStefano Zampini     if (n_D) {
20645f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
20655f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPSolveTranspose(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D));
20665f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
20675f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D));
20685f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScale(pcis->vec2_D,m_one));
206916909a7fSStefano Zampini       if (pcbddc->switch_static) {
20705f80ce2aSJacob Faibussowitsch         CHKERRQ(VecSet(pcis->vec1_N,0.));
20715f80ce2aSJacob Faibussowitsch         CHKERRQ(VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
20725f80ce2aSJacob Faibussowitsch         CHKERRQ(VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
207316909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
20745f80ce2aSJacob Faibussowitsch           CHKERRQ(MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N));
207516909a7fSStefano Zampini         } else {
20765f80ce2aSJacob Faibussowitsch           CHKERRQ(MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N));
20775f80ce2aSJacob Faibussowitsch           CHKERRQ(MatMultTranspose(lA,pcis->vec2_N,pcis->vec1_N));
20785f80ce2aSJacob Faibussowitsch           CHKERRQ(MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N));
207916909a7fSStefano Zampini         }
20805f80ce2aSJacob Faibussowitsch         CHKERRQ(VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD));
20815f80ce2aSJacob Faibussowitsch         CHKERRQ(VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD));
20825f80ce2aSJacob Faibussowitsch         CHKERRQ(VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
20835f80ce2aSJacob Faibussowitsch         CHKERRQ(VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
208416909a7fSStefano Zampini       } else {
20855f80ce2aSJacob Faibussowitsch         CHKERRQ(MatMultTranspose(pcis->A_IB,pcis->vec2_D,pcis->vec1_B));
208616909a7fSStefano Zampini       }
2087b097fa66SStefano Zampini     } else {
20885f80ce2aSJacob Faibussowitsch       CHKERRQ(VecSet(pcis->vec1_B,zero));
2089b097fa66SStefano Zampini     }
20905f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE));
20915f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE));
20925f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCScalingRestriction(pc,z,pcis->vec1_B));
209350efa1b5SStefano Zampini   } else {
20945f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCScalingRestriction(pc,r,pcis->vec1_B));
209550efa1b5SStefano Zampini   }
209650efa1b5SStefano Zampini 
209750efa1b5SStefano Zampini   /* Apply interface preconditioner
209850efa1b5SStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
20995f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCApplyInterfacePreconditioner(pc,PETSC_TRUE));
210050efa1b5SStefano Zampini 
210150efa1b5SStefano Zampini   /* Apply transpose of partition of unity operator */
21025f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCScalingExtension(pc,pcis->vec1_B,z));
210350efa1b5SStefano Zampini 
210450efa1b5SStefano Zampini   /* Second Dirichlet solve and assembling of output */
21055f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
21065f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD));
2107b097fa66SStefano Zampini   if (n_B) {
210816909a7fSStefano Zampini     if (pcbddc->switch_static) {
21095f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
21105f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
21115f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
21125f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE));
211316909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
21145f80ce2aSJacob Faibussowitsch         CHKERRQ(MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N));
211516909a7fSStefano Zampini       } else {
21165f80ce2aSJacob Faibussowitsch         CHKERRQ(MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N));
21175f80ce2aSJacob Faibussowitsch         CHKERRQ(MatMultTranspose(lA,pcis->vec2_N,pcis->vec1_N));
21185f80ce2aSJacob Faibussowitsch         CHKERRQ(MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N));
211916909a7fSStefano Zampini       }
21205f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD));
21215f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD));
212216909a7fSStefano Zampini     } else {
21235f80ce2aSJacob Faibussowitsch       CHKERRQ(MatMultTranspose(pcis->A_BI,pcis->vec1_B,pcis->vec3_D));
212416909a7fSStefano Zampini     }
212516909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
212616909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
21275f80ce2aSJacob Faibussowitsch       CHKERRQ(MatMultTranspose(lA,pcis->vec1_D,pcis->vec3_D));
212816909a7fSStefano Zampini     } else {
21295f80ce2aSJacob Faibussowitsch       CHKERRQ(MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N));
21305f80ce2aSJacob Faibussowitsch       CHKERRQ(MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N));
21315f80ce2aSJacob Faibussowitsch       CHKERRQ(MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D));
213216909a7fSStefano Zampini     }
2133b097fa66SStefano Zampini   }
21345f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
21355f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPSolveTranspose(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D));
21365f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0));
21375f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec4_D));
21388ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
2139b097fa66SStefano Zampini     if (pcbddc->switch_static) {
21405f80ce2aSJacob Faibussowitsch       CHKERRQ(VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D));
2141b097fa66SStefano Zampini     } else {
21425f80ce2aSJacob Faibussowitsch       CHKERRQ(VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D));
2143b097fa66SStefano Zampini     }
21445f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE));
21455f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE));
2146b097fa66SStefano Zampini   } else {
2147b097fa66SStefano Zampini     if (pcbddc->switch_static) {
21485f80ce2aSJacob Faibussowitsch       CHKERRQ(VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D));
2149b097fa66SStefano Zampini     } else {
21505f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScale(pcis->vec4_D,m_one));
2151b097fa66SStefano Zampini     }
21525f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE));
21535f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE));
2154b097fa66SStefano Zampini   }
215527b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
21565f80ce2aSJacob Faibussowitsch     CHKERRQ(PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE));
2157537c1cdfSStefano Zampini   }
21581dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2159f913dca9SStefano Zampini     pcbddc->work_change = r;
21605f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCopy(z,pcbddc->work_change));
21615f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z));
21621dd7afcfSStefano Zampini   }
216350efa1b5SStefano Zampini   PetscFunctionReturn(0);
216450efa1b5SStefano Zampini }
2165674ae819SStefano Zampini 
21669326c5c6Sstefano_zampini PetscErrorCode PCReset_BDDC(PC pc)
2167da1bb401SStefano Zampini {
2168da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
21699326c5c6Sstefano_zampini   PC_IS          *pcis = (PC_IS*)pc->data;
21709326c5c6Sstefano_zampini   KSP            kspD,kspR,kspC;
2171da1bb401SStefano Zampini 
2172da1bb401SStefano Zampini   PetscFunctionBegin;
2173674ae819SStefano Zampini   /* free BDDC custom data  */
21745f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCResetCustomization(pc));
2175674ae819SStefano Zampini   /* destroy objects related to topography */
21765f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCResetTopography(pc));
217734a97f8cSStefano Zampini   /* destroy objects for scaling operator */
21785f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCScalingDestroy(pc));
2179674ae819SStefano Zampini   /* free solvers stuff */
21805f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCResetSolvers(pc));
218162a6ff1dSStefano Zampini   /* free global vectors needed in presolve */
21825f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&pcbddc->temp_solution));
21835f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&pcbddc->original_rhs));
21841dd7afcfSStefano Zampini   /* free data created by PCIS */
21855f80ce2aSJacob Faibussowitsch   CHKERRQ(PCISDestroy(pc));
21869326c5c6Sstefano_zampini 
21879326c5c6Sstefano_zampini   /* restore defaults */
21889326c5c6Sstefano_zampini   kspD = pcbddc->ksp_D;
21899326c5c6Sstefano_zampini   kspR = pcbddc->ksp_R;
21909326c5c6Sstefano_zampini   kspC = pcbddc->coarse_ksp;
21915f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMemzero(pc->data,sizeof(*pcbddc)));
21929326c5c6Sstefano_zampini   pcis->n_neigh                     = -1;
21939326c5c6Sstefano_zampini   pcis->scaling_factor              = 1.0;
21949326c5c6Sstefano_zampini   pcis->reusesubmatrices            = PETSC_TRUE;
21959326c5c6Sstefano_zampini   pcbddc->use_local_adj             = PETSC_TRUE;
21969326c5c6Sstefano_zampini   pcbddc->use_vertices              = PETSC_TRUE;
21979326c5c6Sstefano_zampini   pcbddc->use_edges                 = PETSC_TRUE;
21989326c5c6Sstefano_zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
21999326c5c6Sstefano_zampini   pcbddc->vertex_size               = 1;
22009326c5c6Sstefano_zampini   pcbddc->recompute_topography      = PETSC_TRUE;
22019326c5c6Sstefano_zampini   pcbddc->coarse_size               = -1;
22029326c5c6Sstefano_zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
22039326c5c6Sstefano_zampini   pcbddc->coarsening_ratio          = 8;
22049326c5c6Sstefano_zampini   pcbddc->coarse_eqs_per_proc       = 1;
22059326c5c6Sstefano_zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
22069326c5c6Sstefano_zampini   pcbddc->nedfield                  = -1;
22079326c5c6Sstefano_zampini   pcbddc->nedglobal                 = PETSC_TRUE;
22089326c5c6Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
22099326c5c6Sstefano_zampini   pcbddc->sub_schurs_layers         = -1;
22109326c5c6Sstefano_zampini   pcbddc->ksp_D                     = kspD;
22119326c5c6Sstefano_zampini   pcbddc->ksp_R                     = kspR;
22129326c5c6Sstefano_zampini   pcbddc->coarse_ksp                = kspC;
22139326c5c6Sstefano_zampini   PetscFunctionReturn(0);
22149326c5c6Sstefano_zampini }
22159326c5c6Sstefano_zampini 
22169326c5c6Sstefano_zampini PetscErrorCode PCDestroy_BDDC(PC pc)
22179326c5c6Sstefano_zampini {
22189326c5c6Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
22199326c5c6Sstefano_zampini 
22209326c5c6Sstefano_zampini   PetscFunctionBegin;
22215f80ce2aSJacob Faibussowitsch   CHKERRQ(PCReset_BDDC(pc));
22225f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPDestroy(&pcbddc->ksp_D));
22235f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPDestroy(&pcbddc->ksp_R));
22245f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPDestroy(&pcbddc->coarse_ksp));
22255f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",NULL));
22265f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",NULL));
22275f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",NULL));
22285f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL));
22295f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",NULL));
22305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL));
22315f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL));
22325f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL));
22335f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL));
22345f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL));
22355f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",NULL));
22365f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL));
22375f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",NULL));
22385f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL));
22395f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",NULL));
22405f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL));
22415f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",NULL));
22425f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL));
22435f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",NULL));
22445f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL));
22455f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL));
22465f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL));
22475f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL));
22485f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",NULL));
22495f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",NULL));
22505f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(pc->data));
2251da1bb401SStefano Zampini   PetscFunctionReturn(0);
2252da1bb401SStefano Zampini }
22531e6b0712SBarry Smith 
2254ab8c8b98SStefano Zampini static PetscErrorCode PCSetCoordinates_BDDC(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
2255ab8c8b98SStefano Zampini {
2256ab8c8b98SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2257ab8c8b98SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
2258ab8c8b98SStefano Zampini 
2259ab8c8b98SStefano Zampini   PetscFunctionBegin;
22605f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(mat_graph->coords));
22615f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(nloc*dim,&mat_graph->coords));
22625f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArraycpy(mat_graph->coords,coords,nloc*dim));
2263ab8c8b98SStefano Zampini   mat_graph->cnloc = nloc;
2264ab8c8b98SStefano Zampini   mat_graph->cdim  = dim;
2265ab8c8b98SStefano Zampini   mat_graph->cloc  = PETSC_FALSE;
22664f819b78SStefano Zampini   /* flg setup */
22674f819b78SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
22684f819b78SStefano Zampini   pcbddc->corner_selected = PETSC_FALSE;
2269ab8c8b98SStefano Zampini   PetscFunctionReturn(0);
2270ab8c8b98SStefano Zampini }
2271ab8c8b98SStefano Zampini 
2272a06fd7f2SStefano Zampini static PetscErrorCode PCPreSolveChangeRHS_BDDC(PC pc, PetscBool* change)
2273a06fd7f2SStefano Zampini {
2274a06fd7f2SStefano Zampini   PetscFunctionBegin;
2275a06fd7f2SStefano Zampini   *change = PETSC_TRUE;
2276a06fd7f2SStefano Zampini   PetscFunctionReturn(0);
2277a06fd7f2SStefano Zampini }
2278a06fd7f2SStefano Zampini 
22793425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
22803425bc38SStefano Zampini {
2281674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
2282266e20e9SStefano Zampini   Vec            work;
22833425bc38SStefano Zampini   PC_IS*         pcis;
22843425bc38SStefano Zampini   PC_BDDC*       pcbddc;
22850c7d97c5SJed Brown 
22863425bc38SStefano Zampini   PetscFunctionBegin;
22875f80ce2aSJacob Faibussowitsch   CHKERRQ(MatShellGetContext(fetidp_mat,&mat_ctx));
22883425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
22893425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
22903425bc38SStefano Zampini 
22915f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(fetidp_flux_rhs,0.0));
2292229984c5Sstefano_zampini   /* copy rhs since we may change it during PCPreSolve_BDDC */
2293229984c5Sstefano_zampini   if (!pcbddc->original_rhs) {
22945f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs));
2295229984c5Sstefano_zampini   }
22966cc1294bSstefano_zampini   if (mat_ctx->rhs_flip) {
22975f80ce2aSJacob Faibussowitsch     CHKERRQ(VecPointwiseMult(pcbddc->original_rhs,standard_rhs,mat_ctx->rhs_flip));
22986cc1294bSstefano_zampini   } else {
22995f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCopy(standard_rhs,pcbddc->original_rhs));
23006cc1294bSstefano_zampini   }
2301af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
2302229984c5Sstefano_zampini     /* interface pressure rhs */
23035f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE));
23045f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE));
23055f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterBegin(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD));
23065f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterEnd(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD));
23076cc1294bSstefano_zampini     if (!mat_ctx->rhs_flip) {
23085f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScale(fetidp_flux_rhs,-1.));
2309229984c5Sstefano_zampini     }
23106cc1294bSstefano_zampini   }
2311c08af4c6SStefano Zampini   /*
2312c08af4c6SStefano Zampini      change of basis for physical rhs if needed
2313c08af4c6SStefano Zampini      It also changes the rhs in case of dirichlet boundaries
2314c08af4c6SStefano Zampini   */
23155f80ce2aSJacob Faibussowitsch   CHKERRQ(PCPreSolve_BDDC(mat_ctx->pc,NULL,pcbddc->original_rhs,NULL));
2316fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
23175f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcbddc->original_rhs,pcbddc->work_change));
23183738a8e6SStefano Zampini     work = pcbddc->work_change;
2319fc17d649SStefano Zampini    } else {
23203738a8e6SStefano Zampini     work = pcbddc->original_rhs;
2321fc17d649SStefano Zampini   }
23223425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
23235f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterBegin(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD));
23245f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterEnd(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD));
2325fb223d50SStefano Zampini   /* scale rhs since it should be unassembled */
2326fb223d50SStefano Zampini   /* TODO use counter scaling? (also below) */
23275f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD));
23285f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD));
2329674ae819SStefano Zampini   /* Apply partition of unity */
23305f80ce2aSJacob Faibussowitsch   CHKERRQ(VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B));
23315f80ce2aSJacob Faibussowitsch   /* CHKERRQ(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */
23328eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
23333425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
23345f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0));
23355f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D));
23365f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0));
2337c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
23385f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B));
23395f80ce2aSJacob Faibussowitsch     CHKERRQ(VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B));
23405f80ce2aSJacob Faibussowitsch     CHKERRQ(VecSet(work,0.0));
23415f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE));
23425f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE));
23435f80ce2aSJacob Faibussowitsch     /* CHKERRQ(PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B)); */
23445f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD));
23455f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD));
23465f80ce2aSJacob Faibussowitsch     CHKERRQ(VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B));
23473425bc38SStefano Zampini   }
23483425bc38SStefano Zampini   /* BDDC rhs */
23495f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B));
23508eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
23515f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D));
23523425bc38SStefano Zampini   }
23533425bc38SStefano Zampini   /* apply BDDC */
23545f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n));
23555f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE));
23565f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n));
2357229984c5Sstefano_zampini 
23583425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
23595f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local));
23605f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD));
23615f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterEnd(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD));
2362229984c5Sstefano_zampini   /* Add contribution to interface pressures */
2363229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
23645f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMult(mat_ctx->B_BB,pcis->vec1_B,mat_ctx->vP));
2365229984c5Sstefano_zampini     if (pcbddc->switch_static) {
23665f80ce2aSJacob Faibussowitsch       CHKERRQ(MatMultAdd(mat_ctx->B_BI,pcis->vec1_D,mat_ctx->vP,mat_ctx->vP));
2367229984c5Sstefano_zampini     }
23685f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterBegin(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD));
23695f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterEnd(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD));
2370229984c5Sstefano_zampini   }
23713425bc38SStefano Zampini   PetscFunctionReturn(0);
23723425bc38SStefano Zampini }
23731e6b0712SBarry Smith 
23743425bc38SStefano Zampini /*@
23750f202f7eSStefano Zampini  PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side
23763425bc38SStefano Zampini 
23773425bc38SStefano Zampini    Collective
23783425bc38SStefano Zampini 
23793425bc38SStefano Zampini    Input Parameters:
23800f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix object obtained by a call to PCBDDCCreateFETIDPOperators
23810f202f7eSStefano Zampini -  standard_rhs    - the right-hand side of the original linear system
23823425bc38SStefano Zampini 
23833425bc38SStefano Zampini    Output Parameters:
23840f202f7eSStefano Zampini .  fetidp_flux_rhs - the right-hand side for the FETI-DP linear system
23853425bc38SStefano Zampini 
23863425bc38SStefano Zampini    Level: developer
23873425bc38SStefano Zampini 
23883425bc38SStefano Zampini    Notes:
23893425bc38SStefano Zampini 
23900f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetSolution
23913425bc38SStefano Zampini @*/
23923425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
23933425bc38SStefano Zampini {
2394674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
23953425bc38SStefano Zampini 
23963425bc38SStefano Zampini   PetscFunctionBegin;
2397266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1);
2398266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_rhs,VEC_CLASSID,2);
2399266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_rhs,VEC_CLASSID,3);
24005f80ce2aSJacob Faibussowitsch   CHKERRQ(MatShellGetContext(fetidp_mat,&mat_ctx));
24015f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs)));
24023425bc38SStefano Zampini   PetscFunctionReturn(0);
24033425bc38SStefano Zampini }
24041e6b0712SBarry Smith 
24053425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
24063425bc38SStefano Zampini {
2407674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
24083425bc38SStefano Zampini   PC_IS*         pcis;
24093425bc38SStefano Zampini   PC_BDDC*       pcbddc;
2410229984c5Sstefano_zampini   Vec            work;
24113425bc38SStefano Zampini 
24123425bc38SStefano Zampini   PetscFunctionBegin;
24135f80ce2aSJacob Faibussowitsch   CHKERRQ(MatShellGetContext(fetidp_mat,&mat_ctx));
24143425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
24153425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
24163425bc38SStefano Zampini 
24173425bc38SStefano Zampini   /* apply B_delta^T */
24185f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(pcis->vec1_B,0.));
24195f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE));
24205f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterEnd(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE));
24215f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B));
2422229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
24235f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterBegin(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE));
24245f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterEnd(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE));
24255f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMultAdd(mat_ctx->Bt_BB,mat_ctx->vP,pcis->vec1_B,pcis->vec1_B));
2426229984c5Sstefano_zampini   }
2427229984c5Sstefano_zampini 
24283425bc38SStefano Zampini   /* compute rhs for BDDC application */
24295f80ce2aSJacob Faibussowitsch   CHKERRQ(VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B));
24308eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
24315f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D));
2432229984c5Sstefano_zampini     if (mat_ctx->l2g_p) {
24335f80ce2aSJacob Faibussowitsch       CHKERRQ(VecScale(mat_ctx->vP,-1.));
24345f80ce2aSJacob Faibussowitsch       CHKERRQ(MatMultAdd(mat_ctx->Bt_BI,mat_ctx->vP,pcis->vec1_D,pcis->vec1_D));
24353425bc38SStefano Zampini     }
2436229984c5Sstefano_zampini   }
2437229984c5Sstefano_zampini 
24383425bc38SStefano Zampini   /* apply BDDC */
24395f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n));
24405f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE));
2441229984c5Sstefano_zampini 
2442229984c5Sstefano_zampini   /* put values into global vector */
2443af140850Sstefano_zampini   if (pcbddc->ChangeOfBasisMatrix) work = pcbddc->work_change;
2444af140850Sstefano_zampini   else work = standard_sol;
24455f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterBegin(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE));
24465f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterEnd(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE));
24478eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
24483425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
24495f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D));
24505f80ce2aSJacob Faibussowitsch     CHKERRQ(VecAYPX(pcis->vec1_D,-1.0,mat_ctx->temp_solution_D));
24515f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0));
24525f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec1_D));
24535f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0));
2454c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
24553425bc38SStefano Zampini   }
2456229984c5Sstefano_zampini 
24575f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterBegin(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE));
24585f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterEnd(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE));
2459266e20e9SStefano Zampini   /* add p0 solution to final solution */
24605f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCBenignGetOrSetP0(mat_ctx->pc,work,PETSC_FALSE));
2461fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
24625f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMult(pcbddc->ChangeOfBasisMatrix,work,standard_sol));
2463fc17d649SStefano Zampini   }
24645f80ce2aSJacob Faibussowitsch   CHKERRQ(PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol));
2465af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
24665f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE));
24675f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE));
2468229984c5Sstefano_zampini   }
24693425bc38SStefano Zampini   PetscFunctionReturn(0);
24703425bc38SStefano Zampini }
24711e6b0712SBarry Smith 
24725a1e936bSStefano Zampini static PetscErrorCode PCView_BDDCIPC(PC pc, PetscViewer viewer)
24735a1e936bSStefano Zampini {
24745a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
24755a1e936bSStefano Zampini   PetscBool      isascii;
24765a1e936bSStefano Zampini 
24775a1e936bSStefano Zampini   PetscFunctionBegin;
24785f80ce2aSJacob Faibussowitsch   CHKERRQ(PCShellGetContext(pc,&bddcipc_ctx));
24795f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
24805a1e936bSStefano Zampini   if (isascii) {
24815f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"BDDC interface preconditioner\n"));
24825a1e936bSStefano Zampini   }
24835f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerASCIIPushTab(viewer));
24845f80ce2aSJacob Faibussowitsch   CHKERRQ(PCView(bddcipc_ctx->bddc,viewer));
24855f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerASCIIPopTab(viewer));
24865a1e936bSStefano Zampini   PetscFunctionReturn(0);
24875a1e936bSStefano Zampini }
24885a1e936bSStefano Zampini 
24895a1e936bSStefano Zampini static PetscErrorCode PCSetUp_BDDCIPC(PC pc)
24905a1e936bSStefano Zampini {
24915a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
24925a1e936bSStefano Zampini   PetscBool      isbddc;
24935a1e936bSStefano Zampini   Vec            vv;
24945a1e936bSStefano Zampini   IS             is;
24955a1e936bSStefano Zampini   PC_IS          *pcis;
24965a1e936bSStefano Zampini 
24975a1e936bSStefano Zampini   PetscFunctionBegin;
24985f80ce2aSJacob Faibussowitsch   CHKERRQ(PCShellGetContext(pc,&bddcipc_ctx));
24995f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)bddcipc_ctx->bddc,PCBDDC,&isbddc));
2500*28b400f6SJacob Faibussowitsch   PetscCheck(isbddc,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid type %s. Must be of type bddc",((PetscObject)bddcipc_ctx->bddc)->type_name);
25015f80ce2aSJacob Faibussowitsch   CHKERRQ(PCSetUp(bddcipc_ctx->bddc));
25025a1e936bSStefano Zampini 
25035a1e936bSStefano Zampini   /* create interface scatter */
25045a1e936bSStefano Zampini   pcis = (PC_IS*)(bddcipc_ctx->bddc->data);
25055f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterDestroy(&bddcipc_ctx->g2l));
25065f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateVecs(pc->pmat,&vv,NULL));
25075f80ce2aSJacob Faibussowitsch   CHKERRQ(ISRenumber(pcis->is_B_global,NULL,NULL,&is));
25085f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterCreate(vv,is,pcis->vec1_B,NULL,&bddcipc_ctx->g2l));
25095f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&is));
25105f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&vv));
25115a1e936bSStefano Zampini   PetscFunctionReturn(0);
25125a1e936bSStefano Zampini }
25135a1e936bSStefano Zampini 
25145a1e936bSStefano Zampini static PetscErrorCode PCApply_BDDCIPC(PC pc, Vec r, Vec x)
25155a1e936bSStefano Zampini {
25165a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25175a1e936bSStefano Zampini   PC_IS          *pcis;
25185a1e936bSStefano Zampini   VecScatter     tmps;
25195a1e936bSStefano Zampini 
25205a1e936bSStefano Zampini   PetscFunctionBegin;
25215f80ce2aSJacob Faibussowitsch   CHKERRQ(PCShellGetContext(pc,&bddcipc_ctx));
25225a1e936bSStefano Zampini   pcis = (PC_IS*)(bddcipc_ctx->bddc->data);
25235a1e936bSStefano Zampini   tmps = pcis->global_to_B;
25245a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
25255f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCScalingRestriction(bddcipc_ctx->bddc,r,pcis->vec1_B));
25265f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc,PETSC_FALSE));
25275f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCScalingExtension(bddcipc_ctx->bddc,pcis->vec1_B,x));
25285a1e936bSStefano Zampini   pcis->global_to_B = tmps;
25295a1e936bSStefano Zampini   PetscFunctionReturn(0);
25305a1e936bSStefano Zampini }
25315a1e936bSStefano Zampini 
25325a1e936bSStefano Zampini static PetscErrorCode PCApplyTranspose_BDDCIPC(PC pc, Vec r, Vec x)
25335a1e936bSStefano Zampini {
25345a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25355a1e936bSStefano Zampini   PC_IS          *pcis;
25365a1e936bSStefano Zampini   VecScatter     tmps;
25375a1e936bSStefano Zampini 
25385a1e936bSStefano Zampini   PetscFunctionBegin;
25395f80ce2aSJacob Faibussowitsch   CHKERRQ(PCShellGetContext(pc,&bddcipc_ctx));
25405a1e936bSStefano Zampini   pcis = (PC_IS*)(bddcipc_ctx->bddc->data);
25415a1e936bSStefano Zampini   tmps = pcis->global_to_B;
25425a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
25435f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCScalingRestriction(bddcipc_ctx->bddc,r,pcis->vec1_B));
25445f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc,PETSC_TRUE));
25455f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCScalingExtension(bddcipc_ctx->bddc,pcis->vec1_B,x));
25465a1e936bSStefano Zampini   pcis->global_to_B = tmps;
25475a1e936bSStefano Zampini   PetscFunctionReturn(0);
25485a1e936bSStefano Zampini }
25495a1e936bSStefano Zampini 
25505a1e936bSStefano Zampini static PetscErrorCode PCDestroy_BDDCIPC(PC pc)
25515a1e936bSStefano Zampini {
25525a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25535a1e936bSStefano Zampini 
25545a1e936bSStefano Zampini   PetscFunctionBegin;
25555f80ce2aSJacob Faibussowitsch   CHKERRQ(PCShellGetContext(pc,&bddcipc_ctx));
25565f80ce2aSJacob Faibussowitsch   CHKERRQ(PCDestroy(&bddcipc_ctx->bddc));
25575f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterDestroy(&bddcipc_ctx->g2l));
25585f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(bddcipc_ctx));
25595a1e936bSStefano Zampini   PetscFunctionReturn(0);
25605a1e936bSStefano Zampini }
25615a1e936bSStefano Zampini 
25623425bc38SStefano Zampini /*@
25630f202f7eSStefano Zampini  PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system
25643425bc38SStefano Zampini 
25653425bc38SStefano Zampini    Collective
25663425bc38SStefano Zampini 
25673425bc38SStefano Zampini    Input Parameters:
25680f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators
25690f202f7eSStefano Zampini -  fetidp_flux_sol - the solution of the FETI-DP linear system
25703425bc38SStefano Zampini 
25713425bc38SStefano Zampini    Output Parameters:
25720f202f7eSStefano Zampini .  standard_sol    - the solution defined on the physical domain
25733425bc38SStefano Zampini 
25743425bc38SStefano Zampini    Level: developer
25753425bc38SStefano Zampini 
25763425bc38SStefano Zampini    Notes:
25773425bc38SStefano Zampini 
25780f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetRHS
25793425bc38SStefano Zampini @*/
25803425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
25813425bc38SStefano Zampini {
2582674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
25833425bc38SStefano Zampini 
25843425bc38SStefano Zampini   PetscFunctionBegin;
2585266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1);
2586266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_sol,VEC_CLASSID,2);
2587266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_sol,VEC_CLASSID,3);
25885f80ce2aSJacob Faibussowitsch   CHKERRQ(MatShellGetContext(fetidp_mat,&mat_ctx));
25895f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol)));
25903425bc38SStefano Zampini   PetscFunctionReturn(0);
25913425bc38SStefano Zampini }
25921e6b0712SBarry Smith 
2593547c9a8eSstefano_zampini static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, PetscBool fully_redundant, const char* prefix, Mat *fetidp_mat, PC *fetidp_pc)
25943425bc38SStefano Zampini {
2595674ae819SStefano Zampini 
2596674ae819SStefano Zampini   FETIDPMat_ctx  fetidpmat_ctx;
25973425bc38SStefano Zampini   Mat            newmat;
2598674ae819SStefano Zampini   FETIDPPC_ctx   fetidppc_ctx;
25993425bc38SStefano Zampini   PC             newpc;
2600ce94432eSBarry Smith   MPI_Comm       comm;
26013425bc38SStefano Zampini 
26023425bc38SStefano Zampini   PetscFunctionBegin;
26035f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)pc,&comm));
260415579a77SStefano Zampini   /* FETI-DP matrix */
26055f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx));
26061720468bSStefano Zampini   fetidpmat_ctx->fully_redundant = fully_redundant;
26075f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCSetupFETIDPMatContext(fetidpmat_ctx));
26085f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateShell(comm,fetidpmat_ctx->n,fetidpmat_ctx->n,fetidpmat_ctx->N,fetidpmat_ctx->N,fetidpmat_ctx,&newmat));
26095f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject)newmat,!fetidpmat_ctx->l2g_lambda_only ? "F" : "G"));
26105f80ce2aSJacob Faibussowitsch   CHKERRQ(MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult));
26115f80ce2aSJacob Faibussowitsch   CHKERRQ(MatShellSetOperation(newmat,MATOP_MULT_TRANSPOSE,(void (*)(void))FETIDPMatMultTranspose));
26125f80ce2aSJacob Faibussowitsch   CHKERRQ(MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat));
261315579a77SStefano Zampini   /* propagate MatOptions */
261415579a77SStefano Zampini   {
261515579a77SStefano Zampini     PC_BDDC   *pcbddc = (PC_BDDC*)fetidpmat_ctx->pc->data;
261615579a77SStefano Zampini     PetscBool issym;
261715579a77SStefano Zampini 
26185f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetOption(pc->mat,MAT_SYMMETRIC,&issym));
261915579a77SStefano Zampini     if (issym || pcbddc->symmetric_primal) {
26205f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetOption(newmat,MAT_SYMMETRIC,PETSC_TRUE));
262115579a77SStefano Zampini     }
262215579a77SStefano Zampini   }
26235f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetOptionsPrefix(newmat,prefix));
26245f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAppendOptionsPrefix(newmat,"fetidp_"));
26255f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetUp(newmat));
262615579a77SStefano Zampini   /* FETI-DP preconditioner */
26275f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx));
26285f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx));
26295f80ce2aSJacob Faibussowitsch   CHKERRQ(PCCreate(comm,&newpc));
26305f80ce2aSJacob Faibussowitsch   CHKERRQ(PCSetOperators(newpc,newmat,newmat));
26315f80ce2aSJacob Faibussowitsch   CHKERRQ(PCSetOptionsPrefix(newpc,prefix));
26325f80ce2aSJacob Faibussowitsch   CHKERRQ(PCAppendOptionsPrefix(newpc,"fetidp_"));
26335f80ce2aSJacob Faibussowitsch   CHKERRQ(PCSetErrorIfFailure(newpc,pc->erroriffailure));
263415579a77SStefano Zampini   if (!fetidpmat_ctx->l2g_lambda_only) { /* standard FETI-DP */
26355f80ce2aSJacob Faibussowitsch     CHKERRQ(PCSetType(newpc,PCSHELL));
26365f80ce2aSJacob Faibussowitsch     CHKERRQ(PCShellSetName(newpc,"FETI-DP multipliers"));
26375f80ce2aSJacob Faibussowitsch     CHKERRQ(PCShellSetContext(newpc,fetidppc_ctx));
26385f80ce2aSJacob Faibussowitsch     CHKERRQ(PCShellSetApply(newpc,FETIDPPCApply));
26395f80ce2aSJacob Faibussowitsch     CHKERRQ(PCShellSetApplyTranspose(newpc,FETIDPPCApplyTranspose));
26405f80ce2aSJacob Faibussowitsch     CHKERRQ(PCShellSetView(newpc,FETIDPPCView));
26415f80ce2aSJacob Faibussowitsch     CHKERRQ(PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC));
26425a1e936bSStefano Zampini   } else { /* saddle-point FETI-DP */
26435a1e936bSStefano Zampini     Mat       M;
26445a1e936bSStefano Zampini     PetscInt  psize;
26455a1e936bSStefano Zampini     PetscBool fake = PETSC_FALSE, isfieldsplit;
2646e1214c54Sstefano_zampini 
26475f80ce2aSJacob Faibussowitsch     CHKERRQ(ISViewFromOptions(fetidpmat_ctx->lagrange,NULL,"-lag_view"));
26485f80ce2aSJacob Faibussowitsch     CHKERRQ(ISViewFromOptions(fetidpmat_ctx->pressure,NULL,"-press_view"));
26495f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_PPmat",(PetscObject*)&M));
26505f80ce2aSJacob Faibussowitsch     CHKERRQ(PCSetType(newpc,PCFIELDSPLIT));
26515f80ce2aSJacob Faibussowitsch     CHKERRQ(PCFieldSplitSetIS(newpc,"lag",fetidpmat_ctx->lagrange));
26525f80ce2aSJacob Faibussowitsch     CHKERRQ(PCFieldSplitSetIS(newpc,"p",fetidpmat_ctx->pressure));
26535f80ce2aSJacob Faibussowitsch     CHKERRQ(PCFieldSplitSetType(newpc,PC_COMPOSITE_SCHUR));
26545f80ce2aSJacob Faibussowitsch     CHKERRQ(PCFieldSplitSetSchurFactType(newpc,PC_FIELDSPLIT_SCHUR_FACT_DIAG));
26555f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetSize(fetidpmat_ctx->pressure,&psize));
26565a1e936bSStefano Zampini     if (psize != M->rmap->N) {
26575a1e936bSStefano Zampini       Mat      M2;
26585a1e936bSStefano Zampini       PetscInt lpsize;
26595a1e936bSStefano Zampini 
26605a1e936bSStefano Zampini       fake = PETSC_TRUE;
26615f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetLocalSize(fetidpmat_ctx->pressure,&lpsize));
26625f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreate(comm,&M2));
26635f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetType(M2,MATAIJ));
26645f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetSizes(M2,lpsize,lpsize,psize,psize));
26655f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetUp(M2));
26665f80ce2aSJacob Faibussowitsch       CHKERRQ(MatAssemblyBegin(M2,MAT_FINAL_ASSEMBLY));
26675f80ce2aSJacob Faibussowitsch       CHKERRQ(MatAssemblyEnd(M2,MAT_FINAL_ASSEMBLY));
26685f80ce2aSJacob Faibussowitsch       CHKERRQ(PCFieldSplitSetSchurPre(newpc,PC_FIELDSPLIT_SCHUR_PRE_USER,M2));
26695f80ce2aSJacob Faibussowitsch       CHKERRQ(MatDestroy(&M2));
26705a1e936bSStefano Zampini     } else {
26715f80ce2aSJacob Faibussowitsch       CHKERRQ(PCFieldSplitSetSchurPre(newpc,PC_FIELDSPLIT_SCHUR_PRE_USER,M));
26725a1e936bSStefano Zampini     }
26735f80ce2aSJacob Faibussowitsch     CHKERRQ(PCFieldSplitSetSchurScale(newpc,1.0));
267415579a77SStefano Zampini 
267515579a77SStefano Zampini     /* we need to setfromoptions and setup here to access the blocks */
26765f80ce2aSJacob Faibussowitsch     CHKERRQ(PCSetFromOptions(newpc));
26775f80ce2aSJacob Faibussowitsch     CHKERRQ(PCSetUp(newpc));
2678e1214c54Sstefano_zampini 
26795a1e936bSStefano Zampini     /* user may have changed the type (e.g. -fetidp_pc_type none) */
26805f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectTypeCompare((PetscObject)newpc,PCFIELDSPLIT,&isfieldsplit));
26815a1e936bSStefano Zampini     if (isfieldsplit) {
26825a1e936bSStefano Zampini       KSP       *ksps;
26835a1e936bSStefano Zampini       PC        ppc,lagpc;
26845a1e936bSStefano Zampini       PetscInt  nn;
2685064a4176SStefano Zampini       PetscBool ismatis,matisok = PETSC_FALSE,check = PETSC_FALSE;
26865a1e936bSStefano Zampini 
2687e1214c54Sstefano_zampini       /* set the solver for the (0,0) block */
26885f80ce2aSJacob Faibussowitsch       CHKERRQ(PCFieldSplitSchurGetSubKSP(newpc,&nn,&ksps));
26895a1e936bSStefano Zampini       if (!nn) { /* not of type PC_COMPOSITE_SCHUR */
26905f80ce2aSJacob Faibussowitsch         CHKERRQ(PCFieldSplitGetSubKSP(newpc,&nn,&ksps));
26915a1e936bSStefano Zampini         if (!fake) { /* pass pmat to the pressure solver */
26925a1e936bSStefano Zampini           Mat F;
26935a1e936bSStefano Zampini 
26945f80ce2aSJacob Faibussowitsch           CHKERRQ(KSPGetOperators(ksps[1],&F,NULL));
26955f80ce2aSJacob Faibussowitsch           CHKERRQ(KSPSetOperators(ksps[1],F,M));
26965a1e936bSStefano Zampini         }
26975a1e936bSStefano Zampini       } else {
26985a1e936bSStefano Zampini         PetscBool issym;
26995a1e936bSStefano Zampini         Mat       S;
27005a1e936bSStefano Zampini 
27015f80ce2aSJacob Faibussowitsch         CHKERRQ(PCFieldSplitSchurGetS(newpc,&S));
27025a1e936bSStefano Zampini 
27035f80ce2aSJacob Faibussowitsch         CHKERRQ(MatGetOption(newmat,MAT_SYMMETRIC,&issym));
27045a1e936bSStefano Zampini         if (issym) {
27055f80ce2aSJacob Faibussowitsch           CHKERRQ(MatSetOption(S,MAT_SYMMETRIC,PETSC_TRUE));
27065a1e936bSStefano Zampini         }
27075a1e936bSStefano Zampini       }
27085f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPGetPC(ksps[0],&lagpc));
27095f80ce2aSJacob Faibussowitsch       CHKERRQ(PCSetType(lagpc,PCSHELL));
27105f80ce2aSJacob Faibussowitsch       CHKERRQ(PCShellSetName(lagpc,"FETI-DP multipliers"));
27115f80ce2aSJacob Faibussowitsch       CHKERRQ(PCShellSetContext(lagpc,fetidppc_ctx));
27125f80ce2aSJacob Faibussowitsch       CHKERRQ(PCShellSetApply(lagpc,FETIDPPCApply));
27135f80ce2aSJacob Faibussowitsch       CHKERRQ(PCShellSetApplyTranspose(lagpc,FETIDPPCApplyTranspose));
27145f80ce2aSJacob Faibussowitsch       CHKERRQ(PCShellSetView(lagpc,FETIDPPCView));
27155f80ce2aSJacob Faibussowitsch       CHKERRQ(PCShellSetDestroy(lagpc,PCBDDCDestroyFETIDPPC));
27165a1e936bSStefano Zampini 
27175a1e936bSStefano Zampini       /* Olof's idea: interface Schur complement preconditioner for the mass matrix */
27185f80ce2aSJacob Faibussowitsch       CHKERRQ(KSPGetPC(ksps[1],&ppc));
27195a1e936bSStefano Zampini       if (fake) {
27205a1e936bSStefano Zampini         BDDCIPC_ctx    bddcipc_ctx;
2721ff11fd76SStefano Zampini         PetscContainer c;
27225a1e936bSStefano Zampini 
27235a1e936bSStefano Zampini         matisok = PETSC_TRUE;
27245a1e936bSStefano Zampini 
27255a1e936bSStefano Zampini         /* create inner BDDC solver */
27265f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscNew(&bddcipc_ctx));
27275f80ce2aSJacob Faibussowitsch         CHKERRQ(PCCreate(comm,&bddcipc_ctx->bddc));
27285f80ce2aSJacob Faibussowitsch         CHKERRQ(PCSetType(bddcipc_ctx->bddc,PCBDDC));
27295f80ce2aSJacob Faibussowitsch         CHKERRQ(PCSetOperators(bddcipc_ctx->bddc,M,M));
27305f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_pCSR",(PetscObject*)&c));
27315f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscObjectTypeCompare((PetscObject)M,MATIS,&ismatis));
2732ff11fd76SStefano Zampini         if (c && ismatis) {
2733ff11fd76SStefano Zampini           Mat      lM;
2734ff11fd76SStefano Zampini           PetscInt *csr,n;
2735ff11fd76SStefano Zampini 
27365f80ce2aSJacob Faibussowitsch           CHKERRQ(MatISGetLocalMat(M,&lM));
27375f80ce2aSJacob Faibussowitsch           CHKERRQ(MatGetSize(lM,&n,NULL));
27385f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscContainerGetPointer(c,(void**)&csr));
27395f80ce2aSJacob Faibussowitsch           CHKERRQ(PCBDDCSetLocalAdjacencyGraph(bddcipc_ctx->bddc,n,csr,csr + (n + 1),PETSC_COPY_VALUES));
27405f80ce2aSJacob Faibussowitsch           CHKERRQ(MatISRestoreLocalMat(M,&lM));
2741ff11fd76SStefano Zampini         }
27425f80ce2aSJacob Faibussowitsch         CHKERRQ(PCSetOptionsPrefix(bddcipc_ctx->bddc,((PetscObject)ksps[1])->prefix));
27435f80ce2aSJacob Faibussowitsch         CHKERRQ(PCSetErrorIfFailure(bddcipc_ctx->bddc,pc->erroriffailure));
27445f80ce2aSJacob Faibussowitsch         CHKERRQ(PCSetFromOptions(bddcipc_ctx->bddc));
27455a1e936bSStefano Zampini 
27465a1e936bSStefano Zampini         /* wrap the interface application */
27475f80ce2aSJacob Faibussowitsch         CHKERRQ(PCSetType(ppc,PCSHELL));
27485f80ce2aSJacob Faibussowitsch         CHKERRQ(PCShellSetName(ppc,"FETI-DP pressure"));
27495f80ce2aSJacob Faibussowitsch         CHKERRQ(PCShellSetContext(ppc,bddcipc_ctx));
27505f80ce2aSJacob Faibussowitsch         CHKERRQ(PCShellSetSetUp(ppc,PCSetUp_BDDCIPC));
27515f80ce2aSJacob Faibussowitsch         CHKERRQ(PCShellSetApply(ppc,PCApply_BDDCIPC));
27525f80ce2aSJacob Faibussowitsch         CHKERRQ(PCShellSetApplyTranspose(ppc,PCApplyTranspose_BDDCIPC));
27535f80ce2aSJacob Faibussowitsch         CHKERRQ(PCShellSetView(ppc,PCView_BDDCIPC));
27545f80ce2aSJacob Faibussowitsch         CHKERRQ(PCShellSetDestroy(ppc,PCDestroy_BDDCIPC));
27555a1e936bSStefano Zampini       }
27565a1e936bSStefano Zampini 
27575a1e936bSStefano Zampini       /* determine if we need to assemble M to construct a preconditioner */
27585a1e936bSStefano Zampini       if (!matisok) {
27595f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscObjectTypeCompare((PetscObject)M,MATIS,&ismatis));
27605f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscObjectTypeCompareAny((PetscObject)ppc,&matisok,PCBDDC,PCJACOBI,PCNONE,PCMG,""));
27615a1e936bSStefano Zampini         if (ismatis && !matisok) {
27625f80ce2aSJacob Faibussowitsch           CHKERRQ(MatConvert(M,MATAIJ,MAT_INPLACE_MATRIX,&M));
27635a1e936bSStefano Zampini         }
27645a1e936bSStefano Zampini       }
2765064a4176SStefano Zampini 
2766064a4176SStefano Zampini       /* run the subproblems to check convergence */
27675f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscOptionsGetBool(NULL,((PetscObject)newmat)->prefix,"-check_saddlepoint",&check,NULL));
2768064a4176SStefano Zampini       if (check) {
2769064a4176SStefano Zampini         PetscInt i;
2770064a4176SStefano Zampini 
2771064a4176SStefano Zampini         for (i=0;i<nn;i++) {
2772064a4176SStefano Zampini           KSP       kspC;
2773064a4176SStefano Zampini           PC        pc;
2774064a4176SStefano Zampini           Mat       F,pF;
2775064a4176SStefano Zampini           Vec       x,y;
2776064a4176SStefano Zampini           PetscBool isschur,prec = PETSC_TRUE;
2777064a4176SStefano Zampini 
27785f80ce2aSJacob Faibussowitsch           CHKERRQ(KSPCreate(PetscObjectComm((PetscObject)ksps[i]),&kspC));
27795f80ce2aSJacob Faibussowitsch           CHKERRQ(KSPSetOptionsPrefix(kspC,((PetscObject)ksps[i])->prefix));
27805f80ce2aSJacob Faibussowitsch           CHKERRQ(KSPAppendOptionsPrefix(kspC,"check_"));
27815f80ce2aSJacob Faibussowitsch           CHKERRQ(KSPGetOperators(ksps[i],&F,&pF));
27825f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscObjectTypeCompare((PetscObject)F,MATSCHURCOMPLEMENT,&isschur));
2783064a4176SStefano Zampini           if (isschur) {
2784064a4176SStefano Zampini             KSP  kspS,kspS2;
2785064a4176SStefano Zampini             Mat  A00,pA00,A10,A01,A11;
2786064a4176SStefano Zampini             char prefix[256];
2787064a4176SStefano Zampini 
27885f80ce2aSJacob Faibussowitsch             CHKERRQ(MatSchurComplementGetKSP(F,&kspS));
27895f80ce2aSJacob Faibussowitsch             CHKERRQ(MatSchurComplementGetSubMatrices(F,&A00,&pA00,&A01,&A10,&A11));
27905f80ce2aSJacob Faibussowitsch             CHKERRQ(MatCreateSchurComplement(A00,pA00,A01,A10,A11,&F));
27915f80ce2aSJacob Faibussowitsch             CHKERRQ(MatSchurComplementGetKSP(F,&kspS2));
27925f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscSNPrintf(prefix,sizeof(prefix),"%sschur_",((PetscObject)kspC)->prefix));
27935f80ce2aSJacob Faibussowitsch             CHKERRQ(KSPSetOptionsPrefix(kspS2,prefix));
27945f80ce2aSJacob Faibussowitsch             CHKERRQ(KSPGetPC(kspS2,&pc));
27955f80ce2aSJacob Faibussowitsch             CHKERRQ(PCSetType(pc,PCKSP));
27965f80ce2aSJacob Faibussowitsch             CHKERRQ(PCKSPSetKSP(pc,kspS));
27975f80ce2aSJacob Faibussowitsch             CHKERRQ(KSPSetFromOptions(kspS2));
27985f80ce2aSJacob Faibussowitsch             CHKERRQ(KSPGetPC(kspS2,&pc));
27995f80ce2aSJacob Faibussowitsch             CHKERRQ(PCSetUseAmat(pc,PETSC_TRUE));
2800064a4176SStefano Zampini           } else {
28015f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscObjectReference((PetscObject)F));
2802064a4176SStefano Zampini           }
28035f80ce2aSJacob Faibussowitsch           CHKERRQ(KSPSetFromOptions(kspC));
28045f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscOptionsGetBool(NULL,((PetscObject)kspC)->prefix,"-preconditioned",&prec,NULL));
2805064a4176SStefano Zampini           if (prec)  {
28065f80ce2aSJacob Faibussowitsch             CHKERRQ(KSPGetPC(ksps[i],&pc));
28075f80ce2aSJacob Faibussowitsch             CHKERRQ(KSPSetPC(kspC,pc));
2808064a4176SStefano Zampini           }
28095f80ce2aSJacob Faibussowitsch           CHKERRQ(KSPSetOperators(kspC,F,pF));
28105f80ce2aSJacob Faibussowitsch           CHKERRQ(MatCreateVecs(F,&x,&y));
28115f80ce2aSJacob Faibussowitsch           CHKERRQ(VecSetRandom(x,NULL));
28125f80ce2aSJacob Faibussowitsch           CHKERRQ(MatMult(F,x,y));
28135f80ce2aSJacob Faibussowitsch           CHKERRQ(KSPSolve(kspC,y,x));
28145f80ce2aSJacob Faibussowitsch           CHKERRQ(KSPCheckSolve(kspC,pc,x));
28155f80ce2aSJacob Faibussowitsch           CHKERRQ(KSPDestroy(&kspC));
28165f80ce2aSJacob Faibussowitsch           CHKERRQ(MatDestroy(&F));
28175f80ce2aSJacob Faibussowitsch           CHKERRQ(VecDestroy(&x));
28185f80ce2aSJacob Faibussowitsch           CHKERRQ(VecDestroy(&y));
2819064a4176SStefano Zampini         }
2820064a4176SStefano Zampini       }
28215f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(ksps));
2822e1214c54Sstefano_zampini     }
28235a1e936bSStefano Zampini   }
28243425bc38SStefano Zampini   /* return pointers for objects created */
28253425bc38SStefano Zampini   *fetidp_mat = newmat;
28263425bc38SStefano Zampini   *fetidp_pc  = newpc;
28273425bc38SStefano Zampini   PetscFunctionReturn(0);
28283425bc38SStefano Zampini }
28291e6b0712SBarry Smith 
283094ef8ddeSSatish Balay /*@C
28310f202f7eSStefano Zampini  PCBDDCCreateFETIDPOperators - Create FETI-DP operators
28323425bc38SStefano Zampini 
28333425bc38SStefano Zampini    Collective
28343425bc38SStefano Zampini 
28353425bc38SStefano Zampini    Input Parameters:
28361720468bSStefano Zampini +  pc - the BDDC preconditioning context (setup should have been called before)
2837547c9a8eSstefano_zampini .  fully_redundant - true for a fully redundant set of Lagrange multipliers
2838547c9a8eSstefano_zampini -  prefix - optional options database prefix for the objects to be created (can be NULL)
283928509bceSStefano Zampini 
284028509bceSStefano Zampini    Output Parameters:
28410f202f7eSStefano Zampini +  fetidp_mat - shell FETI-DP matrix object
28420f202f7eSStefano Zampini -  fetidp_pc  - shell Dirichlet preconditioner for FETI-DP matrix
284328509bceSStefano Zampini 
28443425bc38SStefano Zampini    Level: developer
28453425bc38SStefano Zampini 
28463425bc38SStefano Zampini    Notes:
28470f202f7eSStefano Zampini      Currently the only operations provided for FETI-DP matrix are MatMult and MatMultTranspose
28483425bc38SStefano Zampini 
28490f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCMatFETIDPGetRHS, PCBDDCMatFETIDPGetSolution
28503425bc38SStefano Zampini @*/
2851547c9a8eSstefano_zampini PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc)
28523425bc38SStefano Zampini {
28533425bc38SStefano Zampini   PetscFunctionBegin;
28543425bc38SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
28553425bc38SStefano Zampini   if (pc->setupcalled) {
28565f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,PetscBool,const char*,Mat*,PC*),(pc,fully_redundant,prefix,fetidp_mat,fetidp_pc)));
28576080607fSStefano Zampini   } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"You must call PCSetup_BDDC() first");
28583425bc38SStefano Zampini   PetscFunctionReturn(0);
28593425bc38SStefano Zampini }
28600c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
2861da1bb401SStefano Zampini /*MC
2862da1bb401SStefano Zampini    PCBDDC - Balancing Domain Decomposition by Constraints.
28630c7d97c5SJed Brown 
2864be4a8d98Sprj-    An implementation of the BDDC preconditioner based on the bibliography found below.
286528509bceSStefano Zampini 
286628509bceSStefano Zampini    The matrix to be preconditioned (Pmat) must be of type MATIS.
286728509bceSStefano Zampini 
28680f202f7eSStefano Zampini    Currently works with MATIS matrices with local matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers.
286928509bceSStefano Zampini 
287028509bceSStefano Zampini    It also works with unsymmetric and indefinite problems.
287128509bceSStefano Zampini 
2872b6fdb6dfSStefano 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.
2873b6fdb6dfSStefano Zampini 
2874c7017625SStefano 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).
287528509bceSStefano Zampini 
28760f202f7eSStefano 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()
287730368db7SStefano Zampini    Additional information on dofs can be provided by using PCBDDCSetDofsSplitting(), PCBDDCSetDirichletBoundaries(), PCBDDCSetNeumannBoundaries(), and PCBDDCSetPrimalVerticesIS() and their local counterparts.
287828509bceSStefano Zampini 
28790f202f7eSStefano Zampini    Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). Non-singular modes are retained via SVD.
288028509bceSStefano Zampini 
28810f202f7eSStefano 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.
28820f202f7eSStefano Zampini    User defined change of basis can be passed to PCBDDC by using PCBDDCSetChangeOfBasisMat()
288328509bceSStefano Zampini 
28840f202f7eSStefano Zampini    The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using a MatPartitioning object.
288528509bceSStefano Zampini 
2886df4d28bfSStefano 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.
288728509bceSStefano Zampini 
28880f202f7eSStefano 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.
28890f202f7eSStefano Zampini 
2890d314f959SVaclav Hapla    Options Database Keys (some of them, run with -help for a complete list):
28910f202f7eSStefano Zampini 
2892a2b725a8SWilliam Gropp +    -pc_bddc_use_vertices <true> - use or not vertices in primal space
28930f202f7eSStefano Zampini .    -pc_bddc_use_edges <true> - use or not edges in primal space
28940f202f7eSStefano Zampini .    -pc_bddc_use_faces <false> - use or not faces in primal space
28950f202f7eSStefano Zampini .    -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems
28960f202f7eSStefano Zampini .    -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only)
28970f202f7eSStefano Zampini .    -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested
28980f202f7eSStefano Zampini .    -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1])
289928509bceSStefano Zampini .    -pc_bddc_levels <0> - maximum number of levels for multilevel
29000f202f7eSStefano 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)
29015459c157SBarry 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)
29020f202f7eSStefano Zampini .    -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling
290371f2caa7Sprj- .    -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)
2904bd2a564bSStefano 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)
290528509bceSStefano Zampini -    -pc_bddc_check_level <0> - set verbosity level of debugging output
290628509bceSStefano Zampini 
290728509bceSStefano Zampini    Options for Dirichlet, Neumann or coarse solver can be set with
290828509bceSStefano Zampini .vb
290928509bceSStefano Zampini       -pc_bddc_dirichlet_
291028509bceSStefano Zampini       -pc_bddc_neumann_
291128509bceSStefano Zampini       -pc_bddc_coarse_
291228509bceSStefano Zampini .ve
2913f9ff08acSPierre Jolivet    e.g. -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. PCBDDC uses by default KSPPREONLY and PCLU.
291428509bceSStefano Zampini 
29150f202f7eSStefano Zampini    When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified as
291628509bceSStefano Zampini .vb
2917312be037SStefano Zampini       -pc_bddc_dirichlet_lN_
2918312be037SStefano Zampini       -pc_bddc_neumann_lN_
2919312be037SStefano Zampini       -pc_bddc_coarse_lN_
292028509bceSStefano Zampini .ve
29210f202f7eSStefano Zampini    Note that level number ranges from the finest (0) to the coarsest (N).
29220f202f7eSStefano 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.
29230f202f7eSStefano Zampini .vb
29240f202f7eSStefano Zampini      -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3
29250f202f7eSStefano Zampini .ve
29260f202f7eSStefano 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
2927da1bb401SStefano Zampini 
2928be4a8d98Sprj-    References:
2929606c0280SSatish Balay +  * - C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149--168, March 2007
2930606c0280SSatish 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
2931606c0280SSatish Balay .  * - J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", Computing Volume 83, Issue 2--3, pages 55--85, November 2008
2932606c0280SSatish 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
2933be4a8d98Sprj- 
2934da1bb401SStefano Zampini    Level: intermediate
2935da1bb401SStefano Zampini 
2936e94cfbe0SPatrick Sanan    Developer Notes:
2937da1bb401SStefano Zampini 
2938da1bb401SStefano Zampini    Contributed by Stefano Zampini
2939da1bb401SStefano Zampini 
2940da1bb401SStefano Zampini .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
2941da1bb401SStefano Zampini M*/
2942b2573a8aSBarry Smith 
29438cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
2944da1bb401SStefano Zampini {
2945da1bb401SStefano Zampini   PC_BDDC             *pcbddc;
2946da1bb401SStefano Zampini 
2947da1bb401SStefano Zampini   PetscFunctionBegin;
29485f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNewLog(pc,&pcbddc));
29493ec1f749SStefano Zampini   pc->data = pcbddc;
2950da1bb401SStefano Zampini 
2951da1bb401SStefano Zampini   /* create PCIS data structure */
29525f80ce2aSJacob Faibussowitsch   CHKERRQ(PCISCreate(pc));
2953da1bb401SStefano Zampini 
29549326c5c6Sstefano_zampini   /* create local graph structure */
29555f80ce2aSJacob Faibussowitsch   CHKERRQ(PCBDDCGraphCreate(&pcbddc->mat_graph));
29569326c5c6Sstefano_zampini 
29579326c5c6Sstefano_zampini   /* BDDC nonzero defaults */
29586d9e27e4SStefano Zampini   pcbddc->use_nnsp                  = PETSC_TRUE;
295908a5cf49SStefano Zampini   pcbddc->use_local_adj             = PETSC_TRUE;
296047d04d0dSStefano Zampini   pcbddc->use_vertices              = PETSC_TRUE;
296147d04d0dSStefano Zampini   pcbddc->use_edges                 = PETSC_TRUE;
29623301b35fSStefano Zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
296314f95afaSStefano Zampini   pcbddc->vertex_size               = 1;
2964c703fcc7SStefano Zampini   pcbddc->recompute_topography      = PETSC_TRUE;
296568457ee5SStefano Zampini   pcbddc->coarse_size               = -1;
296685c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
296747d04d0dSStefano Zampini   pcbddc->coarsening_ratio          = 8;
296857de7509SStefano Zampini   pcbddc->coarse_eqs_per_proc       = 1;
296927b6a85dSStefano Zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
29701e0482f5SStefano Zampini   pcbddc->nedfield                  = -1;
29711e0482f5SStefano Zampini   pcbddc->nedglobal                 = PETSC_TRUE;
2972be12c134Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
2973b96c3477SStefano Zampini   pcbddc->sub_schurs_layers         = -1;
2974bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[0]     = 0.0;
2975bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[1]     = 0.0;
2976b7eb3628SStefano Zampini 
2977da1bb401SStefano Zampini   /* function pointers */
2978da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
297993bd9ae7SStefano Zampini   pc->ops->applytranspose      = PCApplyTranspose_BDDC;
2980da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
2981da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
2982da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
29836b78500eSPatrick Sanan   pc->ops->view                = PCView_BDDC;
29840a545947SLisandro Dalcin   pc->ops->applyrichardson     = NULL;
29850a545947SLisandro Dalcin   pc->ops->applysymmetricleft  = NULL;
29860a545947SLisandro Dalcin   pc->ops->applysymmetricright = NULL;
2987534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
2988534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
29899326c5c6Sstefano_zampini   pc->ops->reset               = PCReset_BDDC;
2990da1bb401SStefano Zampini 
2991da1bb401SStefano Zampini   /* composing function */
29925f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",PCBDDCSetDiscreteGradient_BDDC));
29935f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",PCBDDCSetDivergenceMat_BDDC));
29945f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",PCBDDCSetChangeOfBasisMat_BDDC));
29955f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC));
29965f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",PCBDDCSetPrimalVerticesIS_BDDC));
29975f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesLocalIS_C",PCBDDCGetPrimalVerticesLocalIS_BDDC));
29985f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesIS_C",PCBDDCGetPrimalVerticesIS_BDDC));
29995f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC));
30005f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC));
30015f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC));
30025f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC));
30035f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC));
30045f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",PCBDDCSetDirichletBoundariesLocal_BDDC));
30055f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC));
30065f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",PCBDDCSetNeumannBoundariesLocal_BDDC));
30075f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC));
30085f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",PCBDDCGetDirichletBoundariesLocal_BDDC));
30095f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC));
30105f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",PCBDDCGetNeumannBoundariesLocal_BDDC));
30115f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC));
30125f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",PCBDDCSetDofsSplittingLocal_BDDC));
30135f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC));
30145f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC));
30155f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC));
30165f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC));
30175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",PCPreSolveChangeRHS_BDDC));
30185f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",PCSetCoordinates_BDDC));
3019da1bb401SStefano Zampini   PetscFunctionReturn(0);
3020da1bb401SStefano Zampini }
302143371fb9SStefano Zampini 
302243371fb9SStefano Zampini /*@C
302343371fb9SStefano Zampini  PCBDDCInitializePackage - This function initializes everything in the PCBDDC package. It is called
30248a690491SBarry Smith     from PCInitializePackage().
302543371fb9SStefano Zampini 
302643371fb9SStefano Zampini  Level: developer
302743371fb9SStefano Zampini 
302843371fb9SStefano Zampini  .seealso: PetscInitialize()
302943371fb9SStefano Zampini @*/
303043371fb9SStefano Zampini PetscErrorCode PCBDDCInitializePackage(void)
303143371fb9SStefano Zampini {
303243371fb9SStefano Zampini   int            i;
303343371fb9SStefano Zampini 
303443371fb9SStefano Zampini   PetscFunctionBegin;
303543371fb9SStefano Zampini   if (PCBDDCPackageInitialized) PetscFunctionReturn(0);
303643371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_TRUE;
30375f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscRegisterFinalize(PCBDDCFinalizePackage));
303843371fb9SStefano Zampini 
303943371fb9SStefano Zampini   /* general events */
30405f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventRegister("PCBDDCTopo",PC_CLASSID,&PC_BDDC_Topology[0]));
30415f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventRegister("PCBDDCLKSP",PC_CLASSID,&PC_BDDC_LocalSolvers[0]));
30425f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventRegister("PCBDDCLWor",PC_CLASSID,&PC_BDDC_LocalWork[0]));
30435f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventRegister("PCBDDCCorr",PC_CLASSID,&PC_BDDC_CorrectionSetUp[0]));
30445f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventRegister("PCBDDCASet",PC_CLASSID,&PC_BDDC_ApproxSetUp[0]));
30455f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventRegister("PCBDDCAApp",PC_CLASSID,&PC_BDDC_ApproxApply[0]));
30465f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventRegister("PCBDDCCSet",PC_CLASSID,&PC_BDDC_CoarseSetUp[0]));
30475f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventRegister("PCBDDCCKSP",PC_CLASSID,&PC_BDDC_CoarseSolver[0]));
30485f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventRegister("PCBDDCAdap",PC_CLASSID,&PC_BDDC_AdaptiveSetUp[0]));
30495f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventRegister("PCBDDCScal",PC_CLASSID,&PC_BDDC_Scaling[0]));
30505f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventRegister("PCBDDCSchr",PC_CLASSID,&PC_BDDC_Schurs[0]));
30515f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventRegister("PCBDDCDirS",PC_CLASSID,&PC_BDDC_Solves[0][0]));
30525f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventRegister("PCBDDCNeuS",PC_CLASSID,&PC_BDDC_Solves[0][1]));
30535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventRegister("PCBDDCCoaS",PC_CLASSID,&PC_BDDC_Solves[0][2]));
305443371fb9SStefano Zampini   for (i=1;i<PETSC_PCBDDC_MAXLEVELS;i++) {
305543371fb9SStefano Zampini     char ename[32];
305643371fb9SStefano Zampini 
30575f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSNPrintf(ename,sizeof(ename),"PCBDDCTopo l%02d",i));
30585f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Topology[i]));
30595f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSNPrintf(ename,sizeof(ename),"PCBDDCLKSP l%02d",i));
30605f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_LocalSolvers[i]));
30615f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSNPrintf(ename,sizeof(ename),"PCBDDCLWor l%02d",i));
30625f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_LocalWork[i]));
30635f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSNPrintf(ename,sizeof(ename),"PCBDDCCorr l%02d",i));
30645f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CorrectionSetUp[i]));
30655f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSNPrintf(ename,sizeof(ename),"PCBDDCASet l%02d",i));
30665f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_ApproxSetUp[i]));
30675f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSNPrintf(ename,sizeof(ename),"PCBDDCAApp l%02d",i));
30685f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_ApproxApply[i]));
30695f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSNPrintf(ename,sizeof(ename),"PCBDDCCSet l%02d",i));
30705f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CoarseSetUp[i]));
30715f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSNPrintf(ename,sizeof(ename),"PCBDDCCKSP l%02d",i));
30725f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CoarseSolver[i]));
30735f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSNPrintf(ename,sizeof(ename),"PCBDDCAdap l%02d",i));
30745f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_AdaptiveSetUp[i]));
30755f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSNPrintf(ename,sizeof(ename),"PCBDDCScal l%02d",i));
30765f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Scaling[i]));
30775f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSNPrintf(ename,sizeof(ename),"PCBDDCSchr l%02d",i));
30785f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Schurs[i]));
30795f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSNPrintf(ename,sizeof(ename),"PCBDDCDirS l%02d",i));
30805f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Solves[i][0]));
30815f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSNPrintf(ename,sizeof(ename),"PCBDDCNeuS l%02d",i));
30825f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Solves[i][1]));
30835f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSNPrintf(ename,sizeof(ename),"PCBDDCCoaS l%02d",i));
30845f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Solves[i][2]));
308543371fb9SStefano Zampini   }
308643371fb9SStefano Zampini   PetscFunctionReturn(0);
308743371fb9SStefano Zampini }
308843371fb9SStefano Zampini 
308943371fb9SStefano Zampini /*@C
309043371fb9SStefano Zampini  PCBDDCFinalizePackage - This function frees everything from the PCBDDC package. It is
309143371fb9SStefano Zampini     called from PetscFinalize() automatically.
309243371fb9SStefano Zampini 
309343371fb9SStefano Zampini  Level: developer
309443371fb9SStefano Zampini 
309543371fb9SStefano Zampini  .seealso: PetscFinalize()
309643371fb9SStefano Zampini @*/
309743371fb9SStefano Zampini PetscErrorCode PCBDDCFinalizePackage(void)
309843371fb9SStefano Zampini {
309943371fb9SStefano Zampini   PetscFunctionBegin;
310043371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_FALSE;
310143371fb9SStefano Zampini   PetscFunctionReturn(0);
310243371fb9SStefano Zampini }
3103