xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 606c028001d6169ccbb8dc4a5aa61aa3bda31a09)
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   PetscErrorCode ierr;
650c7d97c5SJed Brown 
660c7d97c5SJed Brown   PetscFunctionBegin;
67e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"BDDC options");CHKERRQ(ierr);
688eeda7d8SStefano Zampini   /* Verbose debugging */
69a13144ffSStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_check_level","Verbose output for PCBDDC (intended for debug)","none",pcbddc->dbg_flag,&pcbddc->dbg_flag,NULL);CHKERRQ(ierr);
70a13144ffSStefano Zampini   /* Approximate solvers */
71bc960bbfSJed Brown   ierr = 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);CHKERRQ(ierr);
72bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET) {
73c7017625SStefano Zampini     ierr = PetscOptionsBool("-pc_bddc_dirichlet_approximate","Inform PCBDDC that we are using approximate Dirichlet solvers","none",pcbddc->NullSpace_corr[0],&pcbddc->NullSpace_corr[0],NULL);CHKERRQ(ierr);
74c7017625SStefano Zampini     ierr = 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);CHKERRQ(ierr);
75bc960bbfSJed Brown   } else {
76bc960bbfSJed Brown     /* This flag is needed/implied by lumping */
77bc960bbfSJed Brown     pcbddc->switch_static = PETSC_TRUE;
78bc960bbfSJed Brown   }
79c7017625SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_neumann_approximate","Inform PCBDDC that we are using approximate Neumann solvers","none",pcbddc->NullSpace_corr[2],&pcbddc->NullSpace_corr[2],NULL);CHKERRQ(ierr);
80c7017625SStefano Zampini   ierr = 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);CHKERRQ(ierr);
816b78500eSPatrick Sanan   /* Primal space customization */
8208a5cf49SStefano Zampini   ierr = 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);CHKERRQ(ierr);
83be12c134Sstefano_zampini   ierr = PetscOptionsInt("-pc_bddc_graph_maxcount","Maximum number of shared subdomains for a connected component","none",pcbddc->graphmaxcount,&pcbddc->graphmaxcount,NULL);CHKERRQ(ierr);
841c7a958bSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_corner_selection","Activates face-based corner selection","none",pcbddc->corner_selection,&pcbddc->corner_selection,NULL);CHKERRQ(ierr);
858eeda7d8SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_vertices","Use or not corner dofs in coarse space","none",pcbddc->use_vertices,&pcbddc->use_vertices,NULL);CHKERRQ(ierr);
868eeda7d8SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_edges","Use or not edge constraints in coarse space","none",pcbddc->use_edges,&pcbddc->use_edges,NULL);CHKERRQ(ierr);
878eeda7d8SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_faces","Use or not face constraints in coarse space","none",pcbddc->use_faces,&pcbddc->use_faces,NULL);CHKERRQ(ierr);
8814f95afaSStefano Zampini   ierr = 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);CHKERRQ(ierr);
896d9e27e4SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_nnsp","Use near null space attached to the matrix to compute constraints","none",pcbddc->use_nnsp,&pcbddc->use_nnsp,NULL);CHKERRQ(ierr);
906d9e27e4SStefano Zampini   ierr = 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);CHKERRQ(ierr);
9114f95afaSStefano Zampini   ierr = 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);CHKERRQ(ierr);
928eeda7d8SStefano Zampini   /* Change of basis */
93b9b85e73SStefano Zampini   ierr = 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);CHKERRQ(ierr);
94b9b85e73SStefano Zampini   ierr = 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);CHKERRQ(ierr);
95674ae819SStefano Zampini   if (!pcbddc->use_change_of_basis) {
96674ae819SStefano Zampini     pcbddc->use_change_on_faces = PETSC_FALSE;
97674ae819SStefano Zampini   }
988eeda7d8SStefano Zampini   /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */
998eeda7d8SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_switch_static","Switch on static condensation ops around the interface preconditioner","none",pcbddc->switch_static,&pcbddc->switch_static,NULL);CHKERRQ(ierr);
100e569e4e1SStefano Zampini   ierr = 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);CHKERRQ(ierr);
101e569e4e1SStefano Zampini   i    = pcbddc->coarsening_ratio;
102e569e4e1SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","PCBDDCSetCoarseningRatio",i,&i,NULL);CHKERRQ(ierr);
103e569e4e1SStefano Zampini   ierr = PCBDDCSetCoarseningRatio(pc,i);CHKERRQ(ierr);
104e569e4e1SStefano Zampini   i    = pcbddc->max_levels;
105e569e4e1SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_levels","Set maximum number of levels for multilevel","PCBDDCSetLevels",i,&i,NULL);CHKERRQ(ierr);
106e569e4e1SStefano Zampini   ierr = PCBDDCSetLevels(pc,i);CHKERRQ(ierr);
107e569e4e1SStefano Zampini   ierr = 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);CHKERRQ(ierr);
108323d395dSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_coarse_estimates","Use estimated eigenvalues for coarse problem","none",pcbddc->use_coarse_estimates,&pcbddc->use_coarse_estimates,NULL);CHKERRQ(ierr);
109674ae819SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_deluxe_scaling","Use deluxe scaling for BDDC","none",pcbddc->use_deluxe_scaling,&pcbddc->use_deluxe_scaling,NULL);CHKERRQ(ierr);
110b96c3477SStefano Zampini   ierr = 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);CHKERRQ(ierr);
111b96c3477SStefano Zampini   ierr = 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);CHKERRQ(ierr);
112b96c3477SStefano Zampini   ierr = 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);CHKERRQ(ierr);
113683d3df6SStefano Zampini   ierr = 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);CHKERRQ(ierr);
114bf3a8328SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_deluxe_zerorows","Zero rows and columns of deluxe operators associated with primal dofs","none",pcbddc->deluxe_zerorows,&pcbddc->deluxe_zerorows,NULL);CHKERRQ(ierr);
115839e9adbSstefano_zampini   ierr = PetscOptionsBool("-pc_bddc_deluxe_singlemat","Collapse deluxe operators","none",pcbddc->deluxe_singlemat,&pcbddc->deluxe_singlemat,NULL);CHKERRQ(ierr);
116bf3a8328SStefano Zampini   ierr = 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);CHKERRQ(ierr);
117bd2a564bSStefano Zampini   nt   = 2;
118bd2a564bSStefano Zampini   ierr = PetscOptionsRealArray("-pc_bddc_adaptive_threshold","Thresholds to be used for adaptive selection of constraints","none",pcbddc->adaptive_threshold,&nt,NULL);CHKERRQ(ierr);
119bd2a564bSStefano Zampini   if (nt == 1) pcbddc->adaptive_threshold[1] = pcbddc->adaptive_threshold[0];
12008122e43SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_adaptive_nmin","Minimum number of constraints per connected components","none",pcbddc->adaptive_nmin,&pcbddc->adaptive_nmin,NULL);CHKERRQ(ierr);
12108122e43SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_adaptive_nmax","Maximum number of constraints per connected components","none",pcbddc->adaptive_nmax,&pcbddc->adaptive_nmax,NULL);CHKERRQ(ierr);
1223301b35fSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_symmetric","Symmetric computation of primal basis functions","none",pcbddc->symmetric_primal,&pcbddc->symmetric_primal,NULL);CHKERRQ(ierr);
123b0c7d250SStefano Zampini   ierr = 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);CHKERRQ(ierr);
124b3afcdbeSStefano Zampini   ierr = 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);CHKERRQ(ierr);
125e9627c49SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_benign_change","Compute the pressure change of basis explicitly","none",pcbddc->benign_change_explicit,&pcbddc->benign_change_explicit,NULL);CHKERRQ(ierr);
12627b6a85dSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_benign_compute_correction","Compute the benign correction during PreSolve","none",pcbddc->benign_compute_correction,&pcbddc->benign_compute_correction,NULL);CHKERRQ(ierr);
127a198735bSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nonetflux","Automatic computation of no-net-flux quadrature weights","none",pcbddc->compute_nonetflux,&pcbddc->compute_nonetflux,NULL);CHKERRQ(ierr);
1284f1b2e48SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_detect_disconnected","Detects disconnected subdomains","none",pcbddc->detect_disconnected,&pcbddc->detect_disconnected,NULL);CHKERRQ(ierr);
1298361f951SStefano Zampini   ierr = 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);CHKERRQ(ierr);
13070c64980SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_eliminate_dirichlet","Whether or not we want to eliminate dirichlet dofs during presolve","none",pcbddc->eliminate_dirdofs,&pcbddc->eliminate_dirdofs,NULL);CHKERRQ(ierr);
1310c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
1320c7d97c5SJed Brown   PetscFunctionReturn(0);
1330c7d97c5SJed Brown }
1346b78500eSPatrick Sanan 
1356b78500eSPatrick Sanan static PetscErrorCode PCView_BDDC(PC pc,PetscViewer viewer)
1366b78500eSPatrick Sanan {
1376b78500eSPatrick Sanan   PC_BDDC              *pcbddc = (PC_BDDC*)pc->data;
138e9627c49SStefano Zampini   PC_IS                *pcis = (PC_IS*)pc->data;
1396b78500eSPatrick Sanan   PetscErrorCode       ierr;
14071783a16SStefano Zampini   PetscBool            isascii;
141e9627c49SStefano Zampini   PetscSubcomm         subcomm;
142e9627c49SStefano Zampini   PetscViewer          subviewer;
1436b78500eSPatrick Sanan 
1446b78500eSPatrick Sanan   PetscFunctionBegin;
1456b78500eSPatrick Sanan   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1466b78500eSPatrick Sanan   /* ASCII viewer */
1476b78500eSPatrick Sanan   if (isascii) {
1484b2aedd3SStefano Zampini     PetscMPIInt   color,rank,size;
149fbad9177SStefano Zampini     PetscInt64    loc[7],gsum[6],gmax[6],gmin[6],totbenign;
150e9627c49SStefano Zampini     PetscScalar   interface_size;
151e9627c49SStefano Zampini     PetscReal     ratio1=0.,ratio2=0.;
152e9627c49SStefano Zampini     Vec           counter;
1536b78500eSPatrick Sanan 
154b74ba07aSstefano_zampini     if (!pc->setupcalled) {
155b74ba07aSstefano_zampini       ierr = PetscViewerASCIIPrintf(viewer,"  Partial information available: preconditioner has not been setup yet\n");CHKERRQ(ierr);
156b74ba07aSstefano_zampini     }
157efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use verbose output: %D\n",pcbddc->dbg_flag);CHKERRQ(ierr);
1586f0c0a6aSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Use user-defined CSR: %d\n",!!pcbddc->mat_graph->nvtxs_csr);CHKERRQ(ierr);
1596f0c0a6aSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Use local mat graph: %d\n",pcbddc->use_local_adj && !pcbddc->mat_graph->nvtxs_csr);CHKERRQ(ierr);
160e9627c49SStefano Zampini     if (pcbddc->mat_graph->twodim) {
161efd4aadfSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Connectivity graph topological dimension: 2\n");CHKERRQ(ierr);
162e9627c49SStefano Zampini     } else {
163efd4aadfSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Connectivity graph topological dimension: 3\n");CHKERRQ(ierr);
164e9627c49SStefano Zampini     }
165aefa1729SStefano Zampini     if (pcbddc->graphmaxcount != PETSC_MAX_INT) {
166efd4aadfSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Graph max count: %D\n",pcbddc->graphmaxcount);CHKERRQ(ierr);
167aefa1729SStefano Zampini     }
1680dfc91b7SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Corner selection: %d (selected %d)\n",pcbddc->corner_selection,pcbddc->corner_selected);CHKERRQ(ierr);
16950e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Use vertices: %d (vertex size %D)\n",pcbddc->use_vertices,pcbddc->vertex_size);CHKERRQ(ierr);
170efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use edges: %d\n",pcbddc->use_edges);CHKERRQ(ierr);
171efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use faces: %d\n",pcbddc->use_faces);CHKERRQ(ierr);
172efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use true near null space: %d\n",pcbddc->use_nnsp_true);CHKERRQ(ierr);
173efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use QR for single constraints on cc: %d\n",pcbddc->use_qr_single);CHKERRQ(ierr);
174efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use change of basis on local edge nodes: %d\n",pcbddc->use_change_of_basis);CHKERRQ(ierr);
175efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use change of basis on local face nodes: %d\n",pcbddc->use_change_on_faces);CHKERRQ(ierr);
176efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  User defined change of basis matrix: %d\n",!!pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
177efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Has change of basis matrix: %d\n",!!pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
178efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Eliminate dirichlet boundary dofs: %d\n",pcbddc->eliminate_dirdofs);CHKERRQ(ierr);
179efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Switch on static condensation ops around the interface preconditioner: %d\n",pcbddc->switch_static);CHKERRQ(ierr);
180efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use exact dirichlet trick: %d\n",pcbddc->use_exact_dirichlet_trick);CHKERRQ(ierr);
181bc960bbfSJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"  Interface extension: %s\n",PCBDDCInterfaceExtTypes[pcbddc->interface_extension]);CHKERRQ(ierr);
18250e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Multilevel max levels: %D\n",pcbddc->max_levels);CHKERRQ(ierr);
18350e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Multilevel coarsening ratio: %D\n",pcbddc->coarsening_ratio);CHKERRQ(ierr);
184efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use estimated eigs for coarse problem: %d\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
185efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use deluxe scaling: %d\n",pcbddc->use_deluxe_scaling);CHKERRQ(ierr);
186efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use deluxe zerorows: %d\n",pcbddc->deluxe_zerorows);CHKERRQ(ierr);
187efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use deluxe singlemat: %d\n",pcbddc->deluxe_singlemat);CHKERRQ(ierr);
188efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Rebuild interface graph for Schur principal minors: %d\n",pcbddc->sub_schurs_rebuild);CHKERRQ(ierr);
18950e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Number of dofs' layers for the computation of principal minors: %D\n",pcbddc->sub_schurs_layers);CHKERRQ(ierr);
190efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use user CSR graph to compute successive layers: %d\n",pcbddc->sub_schurs_use_useradj);CHKERRQ(ierr);
191bd2a564bSStefano Zampini     if (pcbddc->adaptive_threshold[1] != pcbddc->adaptive_threshold[0]) {
192bd2a564bSStefano Zampini       ierr = 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]);CHKERRQ(ierr);
193bd2a564bSStefano Zampini     } else {
194bd2a564bSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"  Adaptive constraint selection threshold (active %d, userdefined %d): %g\n",pcbddc->adaptive_selection,pcbddc->adaptive_userdefined,pcbddc->adaptive_threshold[0]);CHKERRQ(ierr);
195bd2a564bSStefano Zampini     }
19650e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Min constraints / connected component: %D\n",pcbddc->adaptive_nmin);CHKERRQ(ierr);
19750e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Max constraints / connected component: %D\n",pcbddc->adaptive_nmax);CHKERRQ(ierr);
198efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Invert exact Schur complement for adaptive selection: %d\n",pcbddc->sub_schurs_exact_schur);CHKERRQ(ierr);
199efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Symmetric computation of primal basis functions: %d\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
20050e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Num. Procs. to map coarse adjacency list: %D\n",pcbddc->coarse_adj_red);CHKERRQ(ierr);
20150e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Coarse eqs per proc (significant at the coarsest level): %D\n",pcbddc->coarse_eqs_per_proc);CHKERRQ(ierr);
2028361f951SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Detect disconnected: %d (filter %d)\n",pcbddc->detect_disconnected,pcbddc->detect_disconnected_filter);CHKERRQ(ierr);
203efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Benign subspace trick: %d (change explicit %d)\n",pcbddc->benign_saddle_point,pcbddc->benign_change_explicit);CHKERRQ(ierr);
204efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Benign subspace trick is active: %d\n",pcbddc->benign_have_null);CHKERRQ(ierr);
20515579a77SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Algebraic computation of no-net-flux: %d\n",pcbddc->compute_nonetflux);CHKERRQ(ierr);
206b74ba07aSstefano_zampini     if (!pc->setupcalled) PetscFunctionReturn(0);
2076b78500eSPatrick Sanan 
208fbad9177SStefano Zampini     /* compute interface size */
209e9627c49SStefano Zampini     ierr = VecSet(pcis->vec1_B,1.0);CHKERRQ(ierr);
2100a545947SLisandro Dalcin     ierr = MatCreateVecs(pc->pmat,&counter,NULL);CHKERRQ(ierr);
211e9627c49SStefano Zampini     ierr = VecSet(counter,0.0);CHKERRQ(ierr);
212e9627c49SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
213e9627c49SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
214e9627c49SStefano Zampini     ierr = VecSum(counter,&interface_size);CHKERRQ(ierr);
215e9627c49SStefano Zampini     ierr = VecDestroy(&counter);CHKERRQ(ierr);
216fbad9177SStefano Zampini 
217fbad9177SStefano Zampini     /* compute some statistics on the domain decomposition */
218e9627c49SStefano Zampini     gsum[0] = 1;
219fbad9177SStefano Zampini     gsum[1] = gsum[2] = gsum[3] = gsum[4] = gsum[5] = 0;
220e9627c49SStefano Zampini     loc[0]  = !!pcis->n;
221e9627c49SStefano Zampini     loc[1]  = pcis->n - pcis->n_B;
222e9627c49SStefano Zampini     loc[2]  = pcis->n_B;
223e9627c49SStefano Zampini     loc[3]  = pcbddc->local_primal_size;
224345ecf6cSStefano Zampini     loc[4]  = pcis->n;
225fbad9177SStefano Zampini     loc[5]  = pcbddc->n_local_subs > 0 ? pcbddc->n_local_subs : (pcis->n ? 1 : 0);
226fbad9177SStefano Zampini     loc[6]  = pcbddc->benign_n;
227ffc4695bSBarry Smith     ierr = MPI_Reduce(loc,gsum,6,MPIU_INT64,MPI_SUM,0,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr);
228fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = -1;
229ffc4695bSBarry Smith     ierr = MPI_Reduce(loc,gmax,6,MPIU_INT64,MPI_MAX,0,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr);
230fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = PETSC_MAX_INT;
231ffc4695bSBarry Smith     ierr = MPI_Reduce(loc,gmin,6,MPIU_INT64,MPI_MIN,0,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr);
232ffc4695bSBarry Smith     ierr = MPI_Reduce(&loc[6],&totbenign,1,MPIU_INT64,MPI_SUM,0,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr);
233e9627c49SStefano Zampini     if (pcbddc->coarse_size) {
234e9627c49SStefano Zampini       ratio1 = pc->pmat->rmap->N/(1.*pcbddc->coarse_size);
235e9627c49SStefano Zampini       ratio2 = PetscRealPart(interface_size)/pcbddc->coarse_size;
236e9627c49SStefano Zampini     }
237efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"********************************** STATISTICS AT LEVEL %d **********************************\n",pcbddc->current_level);CHKERRQ(ierr);
23850e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Global dofs sizes: all %D interface %D coarse %D\n",pc->pmat->rmap->N,(PetscInt)PetscRealPart(interface_size),pcbddc->coarse_size);CHKERRQ(ierr);
23950e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Coarsening ratios: all/coarse %D interface/coarse %D\n",(PetscInt)ratio1,(PetscInt)ratio2);CHKERRQ(ierr);
24050e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Active processes : %D\n",(PetscInt)gsum[0]);CHKERRQ(ierr);
24150e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Total subdomains : %D\n",(PetscInt)gsum[5]);CHKERRQ(ierr);
242345ecf6cSStefano Zampini     if (pcbddc->benign_have_null) {
24350e0721cSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"  Benign subs      : %D\n",(PetscInt)totbenign);CHKERRQ(ierr);
244345ecf6cSStefano Zampini     }
24550e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Dofs type        :\tMIN\tMAX\tMEAN\n");CHKERRQ(ierr);
24650e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Interior  dofs   :\t%D\t%D\t%D\n",(PetscInt)gmin[1],(PetscInt)gmax[1],(PetscInt)(gsum[1]/gsum[0]));CHKERRQ(ierr);
24750e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Interface dofs   :\t%D\t%D\t%D\n",(PetscInt)gmin[2],(PetscInt)gmax[2],(PetscInt)(gsum[2]/gsum[0]));CHKERRQ(ierr);
24850e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Primal    dofs   :\t%D\t%D\t%D\n",(PetscInt)gmin[3],(PetscInt)gmax[3],(PetscInt)(gsum[3]/gsum[0]));CHKERRQ(ierr);
24950e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Local     dofs   :\t%D\t%D\t%D\n",(PetscInt)gmin[4],(PetscInt)gmax[4],(PetscInt)(gsum[4]/gsum[0]));CHKERRQ(ierr);
25050e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Local     subs   :\t%D\t%D\n"    ,(PetscInt)gmin[5],(PetscInt)gmax[5]);CHKERRQ(ierr);
25115579a77SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
25215579a77SStefano Zampini 
253ffc4695bSBarry Smith     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRMPI(ierr);
25415579a77SStefano Zampini 
25515579a77SStefano Zampini     /* local solvers */
25615579a77SStefano Zampini     ierr = PetscViewerGetSubViewer(viewer,PetscObjectComm((PetscObject)pcbddc->ksp_D),&subviewer);CHKERRQ(ierr);
257dd400576SPatrick Sanan     if (rank == 0) {
25815579a77SStefano Zampini       ierr = PetscViewerASCIIPrintf(subviewer,"--- Interior solver (rank 0)\n");CHKERRQ(ierr);
25915579a77SStefano Zampini       ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr);
26015579a77SStefano Zampini       ierr = KSPView(pcbddc->ksp_D,subviewer);CHKERRQ(ierr);
26115579a77SStefano Zampini       ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr);
26215579a77SStefano Zampini       ierr = PetscViewerASCIIPrintf(subviewer,"--- Correction solver (rank 0)\n");CHKERRQ(ierr);
26315579a77SStefano Zampini       ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr);
26415579a77SStefano Zampini       ierr = KSPView(pcbddc->ksp_R,subviewer);CHKERRQ(ierr);
26515579a77SStefano Zampini       ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr);
26615579a77SStefano Zampini       ierr = PetscViewerFlush(subviewer);CHKERRQ(ierr);
26715579a77SStefano Zampini     }
26815579a77SStefano Zampini     ierr = PetscViewerRestoreSubViewer(viewer,PetscObjectComm((PetscObject)pcbddc->ksp_D),&subviewer);CHKERRQ(ierr);
26927b6a85dSStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
270e9627c49SStefano Zampini 
271fbad9177SStefano Zampini     /* the coarse problem can be handled by a different communicator */
272e9627c49SStefano Zampini     if (pcbddc->coarse_ksp) color = 1;
273e9627c49SStefano Zampini     else color = 0;
274ffc4695bSBarry Smith     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRMPI(ierr);
275e9627c49SStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)pc),&subcomm);CHKERRQ(ierr);
2764b2aedd3SStefano Zampini     ierr = PetscSubcommSetNumber(subcomm,PetscMin(size,2));CHKERRQ(ierr);
277e9627c49SStefano Zampini     ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
278e9627c49SStefano Zampini     ierr = PetscViewerGetSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer);CHKERRQ(ierr);
279e9627c49SStefano Zampini     if (color == 1) {
28015579a77SStefano Zampini       ierr = PetscViewerASCIIPrintf(subviewer,"--- Coarse solver\n");CHKERRQ(ierr);
28115579a77SStefano Zampini       ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr);
282e9627c49SStefano Zampini       ierr = KSPView(pcbddc->coarse_ksp,subviewer);CHKERRQ(ierr);
28315579a77SStefano Zampini       ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr);
284e9627c49SStefano Zampini       ierr = PetscViewerFlush(subviewer);CHKERRQ(ierr);
285e9627c49SStefano Zampini     }
286e9627c49SStefano Zampini     ierr = PetscViewerRestoreSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer);CHKERRQ(ierr);
287e9627c49SStefano Zampini     ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
288e9627c49SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
289e9627c49SStefano Zampini   }
2906b78500eSPatrick Sanan   PetscFunctionReturn(0);
2916b78500eSPatrick Sanan }
292a13144ffSStefano Zampini 
2931e0482f5SStefano Zampini static PetscErrorCode PCBDDCSetDiscreteGradient_BDDC(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
294a13144ffSStefano Zampini {
295a13144ffSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
296a13144ffSStefano Zampini   PetscErrorCode ierr;
297a13144ffSStefano Zampini 
298a13144ffSStefano Zampini   PetscFunctionBegin;
299a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)G);CHKERRQ(ierr);
300a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
301a13144ffSStefano Zampini   pcbddc->discretegradient = G;
302a13144ffSStefano Zampini   pcbddc->nedorder         = order > 0 ? order : -order;
303495a2a07SStefano Zampini   pcbddc->nedfield         = field;
3041e0482f5SStefano Zampini   pcbddc->nedglobal        = global;
3051e0482f5SStefano Zampini   pcbddc->conforming       = conforming;
306a13144ffSStefano Zampini   PetscFunctionReturn(0);
307a13144ffSStefano Zampini }
308a13144ffSStefano Zampini 
309a13144ffSStefano Zampini /*@
310a13144ffSStefano Zampini  PCBDDCSetDiscreteGradient - Sets the discrete gradient
311a13144ffSStefano Zampini 
312a13144ffSStefano Zampini    Collective on PC
313a13144ffSStefano Zampini 
314a13144ffSStefano Zampini    Input Parameters:
315a13144ffSStefano Zampini +  pc         - the preconditioning context
316a13144ffSStefano Zampini .  G          - the discrete gradient matrix (should be in AIJ format)
317a13144ffSStefano Zampini .  order      - the order of the Nedelec space (1 for the lowest order)
318495a2a07SStefano Zampini .  field      - the field id of the Nedelec dofs (not used if the fields have not been specified)
3191e0482f5SStefano Zampini .  global     - the type of global ordering for the rows of G
320a13144ffSStefano Zampini -  conforming - whether the mesh is conforming or not
321a13144ffSStefano Zampini 
322a13144ffSStefano Zampini    Level: advanced
323a13144ffSStefano Zampini 
32495452b02SPatrick Sanan    Notes:
32595452b02SPatrick Sanan     The discrete gradient matrix G is used to analyze the subdomain edges, and it should not contain any zero entry.
326495a2a07SStefano Zampini           For variable order spaces, the order should be set to zero.
3271e0482f5SStefano Zampini           If global is true, the rows of G should be given in global ordering for the whole dofs;
3281e0482f5SStefano Zampini           if false, the ordering should be global for the Nedelec field.
3291e0482f5SStefano 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
3301e0482f5SStefano Zampini           and geid the one for the Nedelec field.
331a13144ffSStefano Zampini 
332495a2a07SStefano Zampini .seealso: PCBDDC,PCBDDCSetDofsSplitting(),PCBDDCSetDofsSplittingLocal()
333a13144ffSStefano Zampini @*/
3341e0482f5SStefano Zampini PetscErrorCode PCBDDCSetDiscreteGradient(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
335a13144ffSStefano Zampini {
336a13144ffSStefano Zampini   PetscErrorCode ierr;
337a13144ffSStefano Zampini 
338a13144ffSStefano Zampini   PetscFunctionBegin;
339a13144ffSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
340a13144ffSStefano Zampini   PetscValidHeaderSpecific(G,MAT_CLASSID,2);
341a13144ffSStefano Zampini   PetscValidLogicalCollectiveInt(pc,order,3);
3421e0482f5SStefano Zampini   PetscValidLogicalCollectiveInt(pc,field,4);
3431e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc,global,5);
3441e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc,conforming,6);
3451e0482f5SStefano Zampini   PetscCheckSameComm(pc,1,G,2);
3461e0482f5SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDiscreteGradient_C",(PC,Mat,PetscInt,PetscInt,PetscBool,PetscBool),(pc,G,order,field,global,conforming));CHKERRQ(ierr);
347a13144ffSStefano Zampini   PetscFunctionReturn(0);
348a13144ffSStefano Zampini }
349a13144ffSStefano Zampini 
3508ae0ca82SStefano Zampini static PetscErrorCode PCBDDCSetDivergenceMat_BDDC(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
351a198735bSStefano Zampini {
352a198735bSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
353a198735bSStefano Zampini   PetscErrorCode ierr;
3546b78500eSPatrick Sanan 
355a198735bSStefano Zampini   PetscFunctionBegin;
356a198735bSStefano Zampini   ierr = PetscObjectReference((PetscObject)divudotp);CHKERRQ(ierr);
357a198735bSStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
358a198735bSStefano Zampini   pcbddc->divudotp = divudotp;
3598ae0ca82SStefano Zampini   pcbddc->divudotp_trans = trans;
360a198735bSStefano Zampini   pcbddc->compute_nonetflux = PETSC_TRUE;
361a198735bSStefano Zampini   if (vl2l) {
362a198735bSStefano Zampini     ierr = PetscObjectReference((PetscObject)vl2l);CHKERRQ(ierr);
363fa23a32eSStefano Zampini     ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
364a198735bSStefano Zampini     pcbddc->divudotp_vl2l = vl2l;
365a198735bSStefano Zampini   }
366a198735bSStefano Zampini   PetscFunctionReturn(0);
367a198735bSStefano Zampini }
3683d996552SStefano Zampini 
369a198735bSStefano Zampini /*@
370a198735bSStefano Zampini  PCBDDCSetDivergenceMat - Sets the linear operator representing \int_\Omega \div {\bf u} \cdot p dx
371a198735bSStefano Zampini 
372a198735bSStefano Zampini    Collective on PC
373a198735bSStefano Zampini 
374a198735bSStefano Zampini    Input Parameters:
375a198735bSStefano Zampini +  pc - the preconditioning context
376a198735bSStefano Zampini .  divudotp - the matrix (must be of type MATIS)
3778ae0ca82SStefano Zampini .  trans - if trans if false (resp. true), then pressures are in the test (trial) space and velocities are in the trial (test) space.
37805a3bf82SStefano 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
379a198735bSStefano Zampini 
380a198735bSStefano Zampini    Level: advanced
381a198735bSStefano Zampini 
38295452b02SPatrick Sanan    Notes:
38395452b02SPatrick Sanan     This auxiliary matrix is used to compute quadrature weights representing the net-flux across subdomain boundaries
38405a3bf82SStefano Zampini           If vl2l is NULL, the local ordering for velocities in divudotp should match that of the preconditioning matrix
385a198735bSStefano Zampini 
386a198735bSStefano Zampini .seealso: PCBDDC
387a198735bSStefano Zampini @*/
3888ae0ca82SStefano Zampini PetscErrorCode PCBDDCSetDivergenceMat(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
389a198735bSStefano Zampini {
390a198735bSStefano Zampini   PetscBool      ismatis;
391a198735bSStefano Zampini   PetscErrorCode ierr;
392a198735bSStefano Zampini 
393a198735bSStefano Zampini   PetscFunctionBegin;
394a198735bSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
395a198735bSStefano Zampini   PetscValidHeaderSpecific(divudotp,MAT_CLASSID,2);
396a198735bSStefano Zampini   PetscCheckSameComm(pc,1,divudotp,2);
3978ae0ca82SStefano Zampini   PetscValidLogicalCollectiveBool(pc,trans,3);
3981b24a7afSStefano Zampini   if (vl2l) PetscValidHeaderSpecific(vl2l,IS_CLASSID,4);
399a198735bSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)divudotp,MATIS,&ismatis);CHKERRQ(ierr);
4002c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!ismatis,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Divergence matrix needs to be of type MATIS");
4018ae0ca82SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDivergenceMat_C",(PC,Mat,PetscBool,IS),(pc,divudotp,trans,vl2l));CHKERRQ(ierr);
402a198735bSStefano Zampini   PetscFunctionReturn(0);
403a198735bSStefano Zampini }
4042d505d7fSStefano Zampini 
4051dd7afcfSStefano Zampini static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change, PetscBool interior)
406b9b85e73SStefano Zampini {
407b9b85e73SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
408b9b85e73SStefano Zampini   PetscErrorCode ierr;
409b9b85e73SStefano Zampini 
410b9b85e73SStefano Zampini   PetscFunctionBegin;
411b9b85e73SStefano Zampini   ierr = PetscObjectReference((PetscObject)change);CHKERRQ(ierr);
41256282151SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
413b9b85e73SStefano Zampini   pcbddc->user_ChangeOfBasisMatrix = change;
4141dd7afcfSStefano Zampini   pcbddc->change_interior = interior;
415b9b85e73SStefano Zampini   PetscFunctionReturn(0);
416b9b85e73SStefano Zampini }
417b9b85e73SStefano Zampini /*@
418906d46d4SStefano Zampini  PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs
419b9b85e73SStefano Zampini 
420b9b85e73SStefano Zampini    Collective on PC
421b9b85e73SStefano Zampini 
422b9b85e73SStefano Zampini    Input Parameters:
423b9b85e73SStefano Zampini +  pc - the preconditioning context
4241dd7afcfSStefano Zampini .  change - the change of basis matrix
4251dd7afcfSStefano Zampini -  interior - whether or not the change of basis modifies interior dofs
426b9b85e73SStefano Zampini 
427b9b85e73SStefano Zampini    Level: intermediate
428b9b85e73SStefano Zampini 
429b9b85e73SStefano Zampini    Notes:
430b9b85e73SStefano Zampini 
431b9b85e73SStefano Zampini .seealso: PCBDDC
432b9b85e73SStefano Zampini @*/
4331dd7afcfSStefano Zampini PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change, PetscBool interior)
434b9b85e73SStefano Zampini {
435b9b85e73SStefano Zampini   PetscErrorCode ierr;
436b9b85e73SStefano Zampini 
437b9b85e73SStefano Zampini   PetscFunctionBegin;
438b9b85e73SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
439b9b85e73SStefano Zampini   PetscValidHeaderSpecific(change,MAT_CLASSID,2);
440906d46d4SStefano Zampini   PetscCheckSameComm(pc,1,change,2);
441906d46d4SStefano Zampini   if (pc->mat) {
442906d46d4SStefano Zampini     PetscInt rows_c,cols_c,rows,cols;
443906d46d4SStefano Zampini     ierr = MatGetSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
444906d46d4SStefano Zampini     ierr = MatGetSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
4452c71b3e2SJacob 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);
4462c71b3e2SJacob 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);
447906d46d4SStefano Zampini     ierr = MatGetLocalSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
448906d46d4SStefano Zampini     ierr = MatGetLocalSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
4492c71b3e2SJacob 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);
4502c71b3e2SJacob 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);
451906d46d4SStefano Zampini   }
4521dd7afcfSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetChangeOfBasisMat_C",(PC,Mat,PetscBool),(pc,change,interior));CHKERRQ(ierr);
453b9b85e73SStefano Zampini   PetscFunctionReturn(0);
454b9b85e73SStefano Zampini }
4552d505d7fSStefano Zampini 
45630368db7SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesIS_BDDC(PC pc, IS PrimalVertices)
45730368db7SStefano Zampini {
45830368db7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
45956282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
46030368db7SStefano Zampini   PetscErrorCode ierr;
46130368db7SStefano Zampini 
46230368db7SStefano Zampini   PetscFunctionBegin;
46356282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
46456282151SStefano Zampini   if (pcbddc->user_primal_vertices) {
46556282151SStefano Zampini     ierr = ISEqual(PrimalVertices,pcbddc->user_primal_vertices,&isequal);CHKERRQ(ierr);
46656282151SStefano Zampini   }
46730368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
46830368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
46930368db7SStefano Zampini   pcbddc->user_primal_vertices = PrimalVertices;
47056282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
47130368db7SStefano Zampini   PetscFunctionReturn(0);
47230368db7SStefano Zampini }
473ab8c8b98SStefano Zampini 
47430368db7SStefano Zampini /*@
47530368db7SStefano Zampini  PCBDDCSetPrimalVerticesIS - Set additional user defined primal vertices in PCBDDC
47630368db7SStefano Zampini 
47730368db7SStefano Zampini    Collective
47830368db7SStefano Zampini 
47930368db7SStefano Zampini    Input Parameters:
48030368db7SStefano Zampini +  pc - the preconditioning context
48130368db7SStefano Zampini -  PrimalVertices - index set of primal vertices in global numbering (can be empty)
48230368db7SStefano Zampini 
48330368db7SStefano Zampini    Level: intermediate
48430368db7SStefano Zampini 
48530368db7SStefano Zampini    Notes:
48630368db7SStefano Zampini      Any process can list any global node
48730368db7SStefano Zampini 
4883100ebe3SStefano Zampini .seealso: PCBDDC, PCBDDCGetPrimalVerticesIS(), PCBDDCSetPrimalVerticesLocalIS(), PCBDDCGetPrimalVerticesLocalIS()
48930368db7SStefano Zampini @*/
49030368db7SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesIS(PC pc, IS PrimalVertices)
49130368db7SStefano Zampini {
49230368db7SStefano Zampini   PetscErrorCode ierr;
49330368db7SStefano Zampini 
49430368db7SStefano Zampini   PetscFunctionBegin;
49530368db7SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
49630368db7SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
49730368db7SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
49830368db7SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
49930368db7SStefano Zampini   PetscFunctionReturn(0);
50030368db7SStefano Zampini }
5012d505d7fSStefano Zampini 
5023100ebe3SStefano Zampini static PetscErrorCode PCBDDCGetPrimalVerticesIS_BDDC(PC pc, IS *is)
5033100ebe3SStefano Zampini {
5043100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC*)pc->data;
5053100ebe3SStefano Zampini 
5063100ebe3SStefano Zampini   PetscFunctionBegin;
5073100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices;
5083100ebe3SStefano Zampini   PetscFunctionReturn(0);
5093100ebe3SStefano Zampini }
5103100ebe3SStefano Zampini 
5113100ebe3SStefano Zampini /*@
5123100ebe3SStefano Zampini  PCBDDCGetPrimalVerticesIS - Get user defined primal vertices set with PCBDDCSetPrimalVerticesIS()
5133100ebe3SStefano Zampini 
5143100ebe3SStefano Zampini    Collective
5153100ebe3SStefano Zampini 
5163100ebe3SStefano Zampini    Input Parameters:
5173100ebe3SStefano Zampini .  pc - the preconditioning context
5183100ebe3SStefano Zampini 
5193100ebe3SStefano Zampini    Output Parameters:
5203100ebe3SStefano Zampini .  is - index set of primal vertices in global numbering (NULL if not set)
5213100ebe3SStefano Zampini 
5223100ebe3SStefano Zampini    Level: intermediate
5233100ebe3SStefano Zampini 
5243100ebe3SStefano Zampini    Notes:
5253100ebe3SStefano Zampini 
5263100ebe3SStefano Zampini .seealso: PCBDDC, PCBDDCSetPrimalVerticesIS(), PCBDDCSetPrimalVerticesLocalIS(), PCBDDCGetPrimalVerticesLocalIS()
5273100ebe3SStefano Zampini @*/
5283100ebe3SStefano Zampini PetscErrorCode PCBDDCGetPrimalVerticesIS(PC pc, IS *is)
5293100ebe3SStefano Zampini {
5303100ebe3SStefano Zampini   PetscErrorCode ierr;
5313100ebe3SStefano Zampini 
5323100ebe3SStefano Zampini   PetscFunctionBegin;
5333100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5343100ebe3SStefano Zampini   PetscValidPointer(is,2);
5353100ebe3SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetPrimalVerticesIS_C",(PC,IS*),(pc,is));CHKERRQ(ierr);
5363100ebe3SStefano Zampini   PetscFunctionReturn(0);
5373100ebe3SStefano Zampini }
5383100ebe3SStefano Zampini 
539674ae819SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
540674ae819SStefano Zampini {
541674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
54256282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
543674ae819SStefano Zampini   PetscErrorCode ierr;
5441e6b0712SBarry Smith 
545674ae819SStefano Zampini   PetscFunctionBegin;
54656282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
54756282151SStefano Zampini   if (pcbddc->user_primal_vertices_local) {
54856282151SStefano Zampini     ierr = ISEqual(PrimalVertices,pcbddc->user_primal_vertices_local,&isequal);CHKERRQ(ierr);
54956282151SStefano Zampini   }
550674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
55130368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
55230368db7SStefano Zampini   pcbddc->user_primal_vertices_local = PrimalVertices;
55356282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
554674ae819SStefano Zampini   PetscFunctionReturn(0);
555674ae819SStefano Zampini }
5563100ebe3SStefano Zampini 
557674ae819SStefano Zampini /*@
55828509bceSStefano Zampini  PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in PCBDDC
559674ae819SStefano Zampini 
56017eb1463SStefano Zampini    Collective
561674ae819SStefano Zampini 
562674ae819SStefano Zampini    Input Parameters:
563674ae819SStefano Zampini +  pc - the preconditioning context
56417eb1463SStefano Zampini -  PrimalVertices - index set of primal vertices in local numbering (can be empty)
565674ae819SStefano Zampini 
566674ae819SStefano Zampini    Level: intermediate
567674ae819SStefano Zampini 
568674ae819SStefano Zampini    Notes:
569674ae819SStefano Zampini 
5703100ebe3SStefano Zampini .seealso: PCBDDC, PCBDDCSetPrimalVerticesIS(), PCBDDCGetPrimalVerticesIS(), PCBDDCGetPrimalVerticesLocalIS()
571674ae819SStefano Zampini @*/
572674ae819SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
573674ae819SStefano Zampini {
574674ae819SStefano Zampini   PetscErrorCode ierr;
575674ae819SStefano Zampini 
576674ae819SStefano Zampini   PetscFunctionBegin;
577674ae819SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
578674ae819SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
57917eb1463SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
580674ae819SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
581674ae819SStefano Zampini   PetscFunctionReturn(0);
582674ae819SStefano Zampini }
5832d505d7fSStefano Zampini 
5843100ebe3SStefano Zampini static PetscErrorCode PCBDDCGetPrimalVerticesLocalIS_BDDC(PC pc, IS *is)
5853100ebe3SStefano Zampini {
5863100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC*)pc->data;
5873100ebe3SStefano Zampini 
5883100ebe3SStefano Zampini   PetscFunctionBegin;
5893100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices_local;
5903100ebe3SStefano Zampini   PetscFunctionReturn(0);
5913100ebe3SStefano Zampini }
5923100ebe3SStefano Zampini 
5933100ebe3SStefano Zampini /*@
5943100ebe3SStefano Zampini  PCBDDCGetPrimalVerticesLocalIS - Get user defined primal vertices set with PCBDDCSetPrimalVerticesLocalIS()
5953100ebe3SStefano Zampini 
5963100ebe3SStefano Zampini    Collective
5973100ebe3SStefano Zampini 
5983100ebe3SStefano Zampini    Input Parameters:
5993100ebe3SStefano Zampini .  pc - the preconditioning context
6003100ebe3SStefano Zampini 
6013100ebe3SStefano Zampini    Output Parameters:
6023100ebe3SStefano Zampini .  is - index set of primal vertices in local numbering (NULL if not set)
6033100ebe3SStefano Zampini 
6043100ebe3SStefano Zampini    Level: intermediate
6053100ebe3SStefano Zampini 
6063100ebe3SStefano Zampini    Notes:
6073100ebe3SStefano Zampini 
6083100ebe3SStefano Zampini .seealso: PCBDDC, PCBDDCSetPrimalVerticesIS(), PCBDDCGetPrimalVerticesIS(), PCBDDCSetPrimalVerticesLocalIS()
6093100ebe3SStefano Zampini @*/
6103100ebe3SStefano Zampini PetscErrorCode PCBDDCGetPrimalVerticesLocalIS(PC pc, IS *is)
6113100ebe3SStefano Zampini {
6123100ebe3SStefano Zampini   PetscErrorCode ierr;
6133100ebe3SStefano Zampini 
6143100ebe3SStefano Zampini   PetscFunctionBegin;
6153100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
6163100ebe3SStefano Zampini   PetscValidPointer(is,2);
6173100ebe3SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetPrimalVerticesLocalIS_C",(PC,IS*),(pc,is));CHKERRQ(ierr);
6183100ebe3SStefano Zampini   PetscFunctionReturn(0);
6193100ebe3SStefano Zampini }
6203100ebe3SStefano Zampini 
6214fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k)
6224fad6a16SStefano Zampini {
6234fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
6244fad6a16SStefano Zampini 
6254fad6a16SStefano Zampini   PetscFunctionBegin;
6264fad6a16SStefano Zampini   pcbddc->coarsening_ratio = k;
6274fad6a16SStefano Zampini   PetscFunctionReturn(0);
6284fad6a16SStefano Zampini }
6291e6b0712SBarry Smith 
6304fad6a16SStefano Zampini /*@
63128509bceSStefano Zampini  PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel
6324fad6a16SStefano Zampini 
6334fad6a16SStefano Zampini    Logically collective on PC
6344fad6a16SStefano Zampini 
6354fad6a16SStefano Zampini    Input Parameters:
6364fad6a16SStefano Zampini +  pc - the preconditioning context
63728509bceSStefano Zampini -  k - coarsening ratio (H/h at the coarser level)
6384fad6a16SStefano Zampini 
6390f202f7eSStefano Zampini    Options Database Keys:
6400f202f7eSStefano Zampini .    -pc_bddc_coarsening_ratio
6414fad6a16SStefano Zampini 
6424fad6a16SStefano Zampini    Level: intermediate
6434fad6a16SStefano Zampini 
6444fad6a16SStefano Zampini    Notes:
6450f202f7eSStefano Zampini      Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level
6464fad6a16SStefano Zampini 
6470f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetLevels()
6484fad6a16SStefano Zampini @*/
6494fad6a16SStefano Zampini PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k)
6504fad6a16SStefano Zampini {
6514fad6a16SStefano Zampini   PetscErrorCode ierr;
6524fad6a16SStefano Zampini 
6534fad6a16SStefano Zampini   PetscFunctionBegin;
6544fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
6552b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,k,2);
6564fad6a16SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));CHKERRQ(ierr);
6574fad6a16SStefano Zampini   PetscFunctionReturn(0);
6584fad6a16SStefano Zampini }
6592b510759SStefano Zampini 
660b8ffe317SStefano Zampini /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */
661b8ffe317SStefano Zampini static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc,PetscBool flg)
662b8ffe317SStefano Zampini {
663b8ffe317SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
664b8ffe317SStefano Zampini 
665b8ffe317SStefano Zampini   PetscFunctionBegin;
66685c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = flg;
667b8ffe317SStefano Zampini   PetscFunctionReturn(0);
668b8ffe317SStefano Zampini }
669b8ffe317SStefano Zampini 
670b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool flg)
6712b510759SStefano Zampini {
6722b510759SStefano Zampini   PetscErrorCode ierr;
6732b510759SStefano Zampini 
6742b510759SStefano Zampini   PetscFunctionBegin;
6752b510759SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
676b8ffe317SStefano Zampini   PetscValidLogicalCollectiveBool(pc,flg,2);
677b8ffe317SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetUseExactDirichlet_C",(PC,PetscBool),(pc,flg));CHKERRQ(ierr);
6782b510759SStefano Zampini   PetscFunctionReturn(0);
6792b510759SStefano Zampini }
6801e6b0712SBarry Smith 
6812b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc,PetscInt level)
6824fad6a16SStefano Zampini {
6834fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
6844fad6a16SStefano Zampini 
6854fad6a16SStefano Zampini   PetscFunctionBegin;
6862b510759SStefano Zampini   pcbddc->current_level = level;
6874fad6a16SStefano Zampini   PetscFunctionReturn(0);
6884fad6a16SStefano Zampini }
6891e6b0712SBarry Smith 
690b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level)
691b8ffe317SStefano Zampini {
692b8ffe317SStefano Zampini   PetscErrorCode ierr;
693b8ffe317SStefano Zampini 
694b8ffe317SStefano Zampini   PetscFunctionBegin;
695b8ffe317SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
696b8ffe317SStefano Zampini   PetscValidLogicalCollectiveInt(pc,level,2);
697b8ffe317SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLevel_C",(PC,PetscInt),(pc,level));CHKERRQ(ierr);
698b8ffe317SStefano Zampini   PetscFunctionReturn(0);
699b8ffe317SStefano Zampini }
700b8ffe317SStefano Zampini 
7012b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc,PetscInt levels)
7022b510759SStefano Zampini {
7032b510759SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
7042b510759SStefano Zampini 
7052b510759SStefano Zampini   PetscFunctionBegin;
7062c71b3e2SJacob 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);
7072b510759SStefano Zampini   pcbddc->max_levels = levels;
7082b510759SStefano Zampini   PetscFunctionReturn(0);
7092b510759SStefano Zampini }
7102b510759SStefano Zampini 
7114fad6a16SStefano Zampini /*@
71237ebbdf7SStefano Zampini  PCBDDCSetLevels - Sets the maximum number of additional levels allowed for multilevel BDDC
7134fad6a16SStefano Zampini 
7144fad6a16SStefano Zampini    Logically collective on PC
7154fad6a16SStefano Zampini 
7164fad6a16SStefano Zampini    Input Parameters:
7174fad6a16SStefano Zampini +  pc - the preconditioning context
71837ebbdf7SStefano Zampini -  levels - the maximum number of levels
7194fad6a16SStefano Zampini 
7200f202f7eSStefano Zampini    Options Database Keys:
7210f202f7eSStefano Zampini .    -pc_bddc_levels
7224fad6a16SStefano Zampini 
7234fad6a16SStefano Zampini    Level: intermediate
7244fad6a16SStefano Zampini 
7254fad6a16SStefano Zampini    Notes:
72637ebbdf7SStefano Zampini      The default value is 0, that gives the classical two-levels BDDC
7274fad6a16SStefano Zampini 
7280f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetCoarseningRatio()
7294fad6a16SStefano Zampini @*/
7302b510759SStefano Zampini PetscErrorCode PCBDDCSetLevels(PC pc,PetscInt levels)
7314fad6a16SStefano Zampini {
7324fad6a16SStefano Zampini   PetscErrorCode ierr;
7334fad6a16SStefano Zampini 
7344fad6a16SStefano Zampini   PetscFunctionBegin;
7354fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
7362b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,levels,2);
7372b510759SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLevels_C",(PC,PetscInt),(pc,levels));CHKERRQ(ierr);
7384fad6a16SStefano Zampini   PetscFunctionReturn(0);
7394fad6a16SStefano Zampini }
7401e6b0712SBarry Smith 
7413b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
7423b03a366Sstefano_zampini {
7433b03a366Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
74456282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
7453b03a366Sstefano_zampini   PetscErrorCode ierr;
7463b03a366Sstefano_zampini 
7473b03a366Sstefano_zampini   PetscFunctionBegin;
74856282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
74956282151SStefano Zampini   if (pcbddc->DirichletBoundaries) {
75056282151SStefano Zampini     ierr = ISEqual(DirichletBoundaries,pcbddc->DirichletBoundaries,&isequal);CHKERRQ(ierr);
75156282151SStefano Zampini   }
752a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
753785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
7543b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
75536e030ebSStefano Zampini   pcbddc->DirichletBoundaries = DirichletBoundaries;
75656282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7573b03a366Sstefano_zampini   PetscFunctionReturn(0);
7583b03a366Sstefano_zampini }
7591e6b0712SBarry Smith 
7603b03a366Sstefano_zampini /*@
76128509bceSStefano Zampini  PCBDDCSetDirichletBoundaries - Set IS defining Dirichlet boundaries for the global problem.
7623b03a366Sstefano_zampini 
763785d1243SStefano Zampini    Collective
7643b03a366Sstefano_zampini 
7653b03a366Sstefano_zampini    Input Parameters:
7663b03a366Sstefano_zampini +  pc - the preconditioning context
767785d1243SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries
7683b03a366Sstefano_zampini 
7693b03a366Sstefano_zampini    Level: intermediate
7703b03a366Sstefano_zampini 
7710f202f7eSStefano Zampini    Notes:
7720f202f7eSStefano Zampini      Provide the information if you used MatZeroRows/Columns routines. Any process can list any global node
7733b03a366Sstefano_zampini 
7740f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetDirichletBoundariesLocal(), MatZeroRows(), MatZeroRowsColumns()
7753b03a366Sstefano_zampini @*/
7763b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
7773b03a366Sstefano_zampini {
7783b03a366Sstefano_zampini   PetscErrorCode ierr;
7793b03a366Sstefano_zampini 
7803b03a366Sstefano_zampini   PetscFunctionBegin;
7813b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
782674ae819SStefano Zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
783785d1243SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
7843b03a366Sstefano_zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
7853b03a366Sstefano_zampini   PetscFunctionReturn(0);
7863b03a366Sstefano_zampini }
7871e6b0712SBarry Smith 
78882ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc,IS DirichletBoundaries)
7893b03a366Sstefano_zampini {
7903b03a366Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
79156282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
7923b03a366Sstefano_zampini   PetscErrorCode ierr;
7933b03a366Sstefano_zampini 
7943b03a366Sstefano_zampini   PetscFunctionBegin;
79556282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
79656282151SStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
79756282151SStefano Zampini     ierr = ISEqual(DirichletBoundaries,pcbddc->DirichletBoundariesLocal,&isequal);CHKERRQ(ierr);
79856282151SStefano Zampini   }
799a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
800785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
8013b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
802785d1243SStefano Zampini   pcbddc->DirichletBoundariesLocal = DirichletBoundaries;
80356282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
8043b03a366Sstefano_zampini   PetscFunctionReturn(0);
8053b03a366Sstefano_zampini }
8063b03a366Sstefano_zampini 
8073b03a366Sstefano_zampini /*@
80882ba6b80SStefano Zampini  PCBDDCSetDirichletBoundariesLocal - Set IS defining Dirichlet boundaries for the global problem in local ordering.
8093b03a366Sstefano_zampini 
810785d1243SStefano Zampini    Collective
8113b03a366Sstefano_zampini 
8123b03a366Sstefano_zampini    Input Parameters:
8133b03a366Sstefano_zampini +  pc - the preconditioning context
81482ba6b80SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries (in local ordering)
8153b03a366Sstefano_zampini 
8163b03a366Sstefano_zampini    Level: intermediate
8173b03a366Sstefano_zampini 
8183b03a366Sstefano_zampini    Notes:
8193b03a366Sstefano_zampini 
8200f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetDirichletBoundaries(), MatZeroRows(), MatZeroRowsColumns()
8213b03a366Sstefano_zampini @*/
82282ba6b80SStefano Zampini PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc,IS DirichletBoundaries)
8233b03a366Sstefano_zampini {
8243b03a366Sstefano_zampini   PetscErrorCode ierr;
8253b03a366Sstefano_zampini 
8263b03a366Sstefano_zampini   PetscFunctionBegin;
8273b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
8283b03a366Sstefano_zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
82982ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
83082ba6b80SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundariesLocal_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
8313b03a366Sstefano_zampini   PetscFunctionReturn(0);
8323b03a366Sstefano_zampini }
8333b03a366Sstefano_zampini 
83453cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
8350c7d97c5SJed Brown {
8360c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
83756282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
83853cdbc3dSStefano Zampini   PetscErrorCode ierr;
8390c7d97c5SJed Brown 
8400c7d97c5SJed Brown   PetscFunctionBegin;
84156282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
84256282151SStefano Zampini   if (pcbddc->NeumannBoundaries) {
84356282151SStefano Zampini     ierr = ISEqual(NeumannBoundaries,pcbddc->NeumannBoundaries,&isequal);CHKERRQ(ierr);
84456282151SStefano Zampini   }
845a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
846785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
84753cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
84836e030ebSStefano Zampini   pcbddc->NeumannBoundaries = NeumannBoundaries;
84956282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
8500c7d97c5SJed Brown   PetscFunctionReturn(0);
8510c7d97c5SJed Brown }
8521e6b0712SBarry Smith 
85357527edcSJed Brown /*@
85428509bceSStefano Zampini  PCBDDCSetNeumannBoundaries - Set IS defining Neumann boundaries for the global problem.
85557527edcSJed Brown 
856785d1243SStefano Zampini    Collective
85757527edcSJed Brown 
85857527edcSJed Brown    Input Parameters:
85957527edcSJed Brown +  pc - the preconditioning context
860785d1243SStefano Zampini -  NeumannBoundaries - parallel IS defining the Neumann boundaries
86157527edcSJed Brown 
86257527edcSJed Brown    Level: intermediate
86357527edcSJed Brown 
8640f202f7eSStefano Zampini    Notes:
8650f202f7eSStefano Zampini      Any process can list any global node
86657527edcSJed Brown 
8670f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetNeumannBoundariesLocal()
86857527edcSJed Brown @*/
86953cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
8700c7d97c5SJed Brown {
8710c7d97c5SJed Brown   PetscErrorCode ierr;
8720c7d97c5SJed Brown 
8730c7d97c5SJed Brown   PetscFunctionBegin;
8740c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
875674ae819SStefano Zampini   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
876785d1243SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
87753cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
87853cdbc3dSStefano Zampini   PetscFunctionReturn(0);
87953cdbc3dSStefano Zampini }
8801e6b0712SBarry Smith 
88182ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc,IS NeumannBoundaries)
8820c7d97c5SJed Brown {
8830c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
88456282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
8850c7d97c5SJed Brown   PetscErrorCode ierr;
8860c7d97c5SJed Brown 
8870c7d97c5SJed Brown   PetscFunctionBegin;
88856282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
88956282151SStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
89056282151SStefano Zampini     ierr = ISEqual(NeumannBoundaries,pcbddc->NeumannBoundariesLocal,&isequal);CHKERRQ(ierr);
89156282151SStefano Zampini   }
892a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
893785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
8940c7d97c5SJed Brown   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
895785d1243SStefano Zampini   pcbddc->NeumannBoundariesLocal = NeumannBoundaries;
89656282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
8970c7d97c5SJed Brown   PetscFunctionReturn(0);
8980c7d97c5SJed Brown }
8990c7d97c5SJed Brown 
9000c7d97c5SJed Brown /*@
90182ba6b80SStefano Zampini  PCBDDCSetNeumannBoundariesLocal - Set IS defining Neumann boundaries for the global problem in local ordering.
9020c7d97c5SJed Brown 
903785d1243SStefano Zampini    Collective
9040c7d97c5SJed Brown 
9050c7d97c5SJed Brown    Input Parameters:
9060c7d97c5SJed Brown +  pc - the preconditioning context
90782ba6b80SStefano Zampini -  NeumannBoundaries - parallel IS defining the subdomain part of Neumann boundaries (in local ordering)
9080c7d97c5SJed Brown 
9090c7d97c5SJed Brown    Level: intermediate
9100c7d97c5SJed Brown 
9110c7d97c5SJed Brown    Notes:
9120c7d97c5SJed Brown 
9130f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetNeumannBoundaries()
9140c7d97c5SJed Brown @*/
91582ba6b80SStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc,IS NeumannBoundaries)
9160c7d97c5SJed Brown {
9170c7d97c5SJed Brown   PetscErrorCode ierr;
9180c7d97c5SJed Brown 
9190c7d97c5SJed Brown   PetscFunctionBegin;
9200c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
9210c7d97c5SJed Brown   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
92282ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
92382ba6b80SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundariesLocal_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
92453cdbc3dSStefano Zampini   PetscFunctionReturn(0);
92553cdbc3dSStefano Zampini }
92653cdbc3dSStefano Zampini 
927da1bb401SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
928da1bb401SStefano Zampini {
929da1bb401SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
930da1bb401SStefano Zampini 
931da1bb401SStefano Zampini   PetscFunctionBegin;
932da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
933da1bb401SStefano Zampini   PetscFunctionReturn(0);
934da1bb401SStefano Zampini }
9351e6b0712SBarry Smith 
936da1bb401SStefano Zampini /*@
937785d1243SStefano Zampini  PCBDDCGetDirichletBoundaries - Get parallel IS for Dirichlet boundaries
938da1bb401SStefano Zampini 
939785d1243SStefano Zampini    Collective
940785d1243SStefano Zampini 
941785d1243SStefano Zampini    Input Parameters:
942785d1243SStefano Zampini .  pc - the preconditioning context
943785d1243SStefano Zampini 
944785d1243SStefano Zampini    Output Parameters:
945785d1243SStefano Zampini .  DirichletBoundaries - index set defining the Dirichlet boundaries
946785d1243SStefano Zampini 
947785d1243SStefano Zampini    Level: intermediate
948785d1243SStefano Zampini 
9490f202f7eSStefano Zampini    Notes:
9500f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetDirichletBoundaries
951785d1243SStefano Zampini 
952785d1243SStefano Zampini .seealso: PCBDDC
953785d1243SStefano Zampini @*/
954785d1243SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
955785d1243SStefano Zampini {
956785d1243SStefano Zampini   PetscErrorCode ierr;
957785d1243SStefano Zampini 
958785d1243SStefano Zampini   PetscFunctionBegin;
959785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
960785d1243SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
961785d1243SStefano Zampini   PetscFunctionReturn(0);
962785d1243SStefano Zampini }
963785d1243SStefano Zampini 
964785d1243SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc,IS *DirichletBoundaries)
965785d1243SStefano Zampini {
966785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
967785d1243SStefano Zampini 
968785d1243SStefano Zampini   PetscFunctionBegin;
969785d1243SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundariesLocal;
970785d1243SStefano Zampini   PetscFunctionReturn(0);
971785d1243SStefano Zampini }
972785d1243SStefano Zampini 
973da1bb401SStefano Zampini /*@
97482ba6b80SStefano Zampini  PCBDDCGetDirichletBoundariesLocal - Get parallel IS for Dirichlet boundaries (in local ordering)
975da1bb401SStefano Zampini 
976785d1243SStefano Zampini    Collective
977da1bb401SStefano Zampini 
978da1bb401SStefano Zampini    Input Parameters:
97928509bceSStefano Zampini .  pc - the preconditioning context
980da1bb401SStefano Zampini 
981da1bb401SStefano Zampini    Output Parameters:
98228509bceSStefano Zampini .  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
983da1bb401SStefano Zampini 
984da1bb401SStefano Zampini    Level: intermediate
985da1bb401SStefano Zampini 
986da1bb401SStefano Zampini    Notes:
9870f202f7eSStefano 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).
9880f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
989da1bb401SStefano Zampini 
990da1bb401SStefano Zampini .seealso: PCBDDC
991da1bb401SStefano Zampini @*/
99282ba6b80SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc,IS *DirichletBoundaries)
993da1bb401SStefano Zampini {
994da1bb401SStefano Zampini   PetscErrorCode ierr;
995da1bb401SStefano Zampini 
996da1bb401SStefano Zampini   PetscFunctionBegin;
997da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
99882ba6b80SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundariesLocal_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
999da1bb401SStefano Zampini   PetscFunctionReturn(0);
1000da1bb401SStefano Zampini }
10011e6b0712SBarry Smith 
100253cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
100353cdbc3dSStefano Zampini {
100453cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
100553cdbc3dSStefano Zampini 
100653cdbc3dSStefano Zampini   PetscFunctionBegin;
100753cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
100853cdbc3dSStefano Zampini   PetscFunctionReturn(0);
100953cdbc3dSStefano Zampini }
10101e6b0712SBarry Smith 
101153cdbc3dSStefano Zampini /*@
1012785d1243SStefano Zampini  PCBDDCGetNeumannBoundaries - Get parallel IS for Neumann boundaries
101353cdbc3dSStefano Zampini 
1014785d1243SStefano Zampini    Collective
1015785d1243SStefano Zampini 
1016785d1243SStefano Zampini    Input Parameters:
1017785d1243SStefano Zampini .  pc - the preconditioning context
1018785d1243SStefano Zampini 
1019785d1243SStefano Zampini    Output Parameters:
1020785d1243SStefano Zampini .  NeumannBoundaries - index set defining the Neumann boundaries
1021785d1243SStefano Zampini 
1022785d1243SStefano Zampini    Level: intermediate
1023785d1243SStefano Zampini 
10240f202f7eSStefano Zampini    Notes:
10250f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetNeumannBoundaries
1026785d1243SStefano Zampini 
1027785d1243SStefano Zampini .seealso: PCBDDC
1028785d1243SStefano Zampini @*/
1029785d1243SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
1030785d1243SStefano Zampini {
1031785d1243SStefano Zampini   PetscErrorCode ierr;
1032785d1243SStefano Zampini 
1033785d1243SStefano Zampini   PetscFunctionBegin;
1034785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1035785d1243SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
1036785d1243SStefano Zampini   PetscFunctionReturn(0);
1037785d1243SStefano Zampini }
1038785d1243SStefano Zampini 
1039785d1243SStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc,IS *NeumannBoundaries)
1040785d1243SStefano Zampini {
1041785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1042785d1243SStefano Zampini 
1043785d1243SStefano Zampini   PetscFunctionBegin;
1044785d1243SStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundariesLocal;
1045785d1243SStefano Zampini   PetscFunctionReturn(0);
1046785d1243SStefano Zampini }
1047785d1243SStefano Zampini 
104853cdbc3dSStefano Zampini /*@
104982ba6b80SStefano Zampini  PCBDDCGetNeumannBoundariesLocal - Get parallel IS for Neumann boundaries (in local ordering)
105053cdbc3dSStefano Zampini 
1051785d1243SStefano Zampini    Collective
105253cdbc3dSStefano Zampini 
105353cdbc3dSStefano Zampini    Input Parameters:
105428509bceSStefano Zampini .  pc - the preconditioning context
105553cdbc3dSStefano Zampini 
105653cdbc3dSStefano Zampini    Output Parameters:
105728509bceSStefano Zampini .  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
105853cdbc3dSStefano Zampini 
105953cdbc3dSStefano Zampini    Level: intermediate
106053cdbc3dSStefano Zampini 
106153cdbc3dSStefano Zampini    Notes:
10620f202f7eSStefano 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).
10630f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
106453cdbc3dSStefano Zampini 
106553cdbc3dSStefano Zampini .seealso: PCBDDC
106653cdbc3dSStefano Zampini @*/
106782ba6b80SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc,IS *NeumannBoundaries)
106853cdbc3dSStefano Zampini {
106953cdbc3dSStefano Zampini   PetscErrorCode ierr;
107053cdbc3dSStefano Zampini 
107153cdbc3dSStefano Zampini   PetscFunctionBegin;
107253cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
107382ba6b80SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundariesLocal_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
10740c7d97c5SJed Brown   PetscFunctionReturn(0);
10750c7d97c5SJed Brown }
10761e6b0712SBarry Smith 
10771a83f524SJed Brown static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
107836e030ebSStefano Zampini {
107936e030ebSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1080da1bb401SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
108156282151SStefano Zampini   PetscBool      same_data = PETSC_FALSE;
1082da1bb401SStefano Zampini   PetscErrorCode ierr;
108336e030ebSStefano Zampini 
108436e030ebSStefano Zampini   PetscFunctionBegin;
10858687889aSStefano Zampini   if (!nvtxs) {
108604194a47SStefano Zampini     if (copymode == PETSC_OWN_POINTER) {
108704194a47SStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
108804194a47SStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
108904194a47SStefano Zampini     }
10908687889aSStefano Zampini     ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
10918687889aSStefano Zampini     PetscFunctionReturn(0);
10928687889aSStefano Zampini   }
109366da6bd7Sstefano_zampini   if (mat_graph->nvtxs == nvtxs && mat_graph->freecsr) { /* we own the data */
109456282151SStefano Zampini     if (mat_graph->xadj == xadj && mat_graph->adjncy == adjncy) same_data = PETSC_TRUE;
109556282151SStefano Zampini     if (!same_data && mat_graph->xadj[nvtxs] == xadj[nvtxs]) {
1096580bdb30SBarry Smith       ierr = PetscArraycmp(xadj,mat_graph->xadj,nvtxs+1,&same_data);CHKERRQ(ierr);
10972d505d7fSStefano Zampini       if (same_data) {
1098580bdb30SBarry Smith         ierr = PetscArraycmp(adjncy,mat_graph->adjncy,xadj[nvtxs],&same_data);CHKERRQ(ierr);
10992d505d7fSStefano Zampini       }
110056282151SStefano Zampini     }
110156282151SStefano Zampini   }
110256282151SStefano Zampini   if (!same_data) {
1103674ae819SStefano Zampini     /* free old CSR */
1104674ae819SStefano Zampini     ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
1105674ae819SStefano Zampini     /* get CSR into graph structure */
1106da1bb401SStefano Zampini     if (copymode == PETSC_COPY_VALUES) {
1107854ce69bSBarry Smith       ierr = PetscMalloc1(nvtxs+1,&mat_graph->xadj);CHKERRQ(ierr);
1108785e854fSJed Brown       ierr = PetscMalloc1(xadj[nvtxs],&mat_graph->adjncy);CHKERRQ(ierr);
1109580bdb30SBarry Smith       ierr = PetscArraycpy(mat_graph->xadj,xadj,nvtxs+1);CHKERRQ(ierr);
1110580bdb30SBarry Smith       ierr = PetscArraycpy(mat_graph->adjncy,adjncy,xadj[nvtxs]);CHKERRQ(ierr);
1111a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1112da1bb401SStefano Zampini     } else if (copymode == PETSC_OWN_POINTER) {
11131a83f524SJed Brown       mat_graph->xadj    = (PetscInt*)xadj;
11141a83f524SJed Brown       mat_graph->adjncy  = (PetscInt*)adjncy;
1115a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1116a1dbd327SStefano Zampini     } else if (copymode == PETSC_USE_POINTER) {
1117a1dbd327SStefano Zampini       mat_graph->xadj    = (PetscInt*)xadj;
1118a1dbd327SStefano Zampini       mat_graph->adjncy  = (PetscInt*)adjncy;
1119a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_FALSE;
112098921bdaSJacob Faibussowitsch     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %D",copymode);
1121575ad6abSStefano Zampini     mat_graph->nvtxs_csr = nvtxs;
112256282151SStefano Zampini     pcbddc->recompute_topography = PETSC_TRUE;
112356282151SStefano Zampini   }
112436e030ebSStefano Zampini   PetscFunctionReturn(0);
112536e030ebSStefano Zampini }
11261e6b0712SBarry Smith 
112736e030ebSStefano Zampini /*@
112854fffbccSStefano Zampini  PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local degrees of freedom.
112936e030ebSStefano Zampini 
113036e030ebSStefano Zampini    Not collective
113136e030ebSStefano Zampini 
113236e030ebSStefano Zampini    Input Parameters:
113354fffbccSStefano Zampini +  pc - the preconditioning context.
113454fffbccSStefano Zampini .  nvtxs - number of local vertices of the graph (i.e., the number of local dofs).
113554fffbccSStefano Zampini .  xadj, adjncy - the connectivity of the dofs in CSR format.
113654fffbccSStefano Zampini -  copymode - supported modes are PETSC_COPY_VALUES, PETSC_USE_POINTER or PETSC_OWN_POINTER.
113736e030ebSStefano Zampini 
113836e030ebSStefano Zampini    Level: intermediate
113936e030ebSStefano Zampini 
114095452b02SPatrick Sanan    Notes:
114195452b02SPatrick Sanan     A dof is considered connected with all local dofs if xadj[dof+1]-xadj[dof] == 1 and adjncy[xadj[dof]] is negative.
114236e030ebSStefano Zampini 
114328509bceSStefano Zampini .seealso: PCBDDC,PetscCopyMode
114436e030ebSStefano Zampini @*/
11451a83f524SJed Brown PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
114636e030ebSStefano Zampini {
11470a545947SLisandro Dalcin   void (*f)(void) = NULL;
114836e030ebSStefano Zampini   PetscErrorCode ierr;
114936e030ebSStefano Zampini 
115036e030ebSStefano Zampini   PetscFunctionBegin;
115136e030ebSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
11528687889aSStefano Zampini   if (nvtxs) {
1153674ae819SStefano Zampini     PetscValidIntPointer(xadj,3);
11541633d1f0SStefano Zampini     if (xadj[nvtxs]) PetscValidIntPointer(adjncy,4);
11558687889aSStefano Zampini   }
11561a83f524SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
1157575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
1158575ad6abSStefano Zampini   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr);
1159575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
1160575ad6abSStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
1161575ad6abSStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
1162da1bb401SStefano Zampini   }
116336e030ebSStefano Zampini   PetscFunctionReturn(0);
116436e030ebSStefano Zampini }
11651e6b0712SBarry Smith 
116663602bcaSStefano Zampini static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
116763602bcaSStefano Zampini {
116863602bcaSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
116963602bcaSStefano Zampini   PetscInt       i;
117056282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
117163602bcaSStefano Zampini   PetscErrorCode ierr;
117263602bcaSStefano Zampini 
117363602bcaSStefano Zampini   PetscFunctionBegin;
117456282151SStefano Zampini   if (pcbddc->n_ISForDofsLocal == n_is) {
117556282151SStefano Zampini     for (i=0;i<n_is;i++) {
117656282151SStefano Zampini       PetscBool isequalt;
117756282151SStefano Zampini       ierr = ISEqual(ISForDofs[i],pcbddc->ISForDofsLocal[i],&isequalt);CHKERRQ(ierr);
117856282151SStefano Zampini       if (!isequalt) break;
117956282151SStefano Zampini     }
118056282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
118156282151SStefano Zampini   }
118256282151SStefano Zampini   for (i=0;i<n_is;i++) {
118356282151SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
118456282151SStefano Zampini   }
118563602bcaSStefano Zampini   /* Destroy ISes if they were already set */
118663602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
118763602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
118863602bcaSStefano Zampini   }
118963602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
1190a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
119163602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
119263602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
119363602bcaSStefano Zampini   }
119463602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
119563602bcaSStefano Zampini   pcbddc->n_ISForDofs = 0;
119663602bcaSStefano Zampini   /* allocate space then set */
1197d02579f5SStefano Zampini   if (n_is) {
1198d02579f5SStefano Zampini     ierr = PetscMalloc1(n_is,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
1199d02579f5SStefano Zampini   }
120063602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
120163602bcaSStefano Zampini     pcbddc->ISForDofsLocal[i] = ISForDofs[i];
120263602bcaSStefano Zampini   }
120363602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = n_is;
120463602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
120556282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
120663602bcaSStefano Zampini   PetscFunctionReturn(0);
120763602bcaSStefano Zampini }
120863602bcaSStefano Zampini 
120963602bcaSStefano Zampini /*@
121063602bcaSStefano Zampini  PCBDDCSetDofsSplittingLocal - Set index sets defining fields of the local subdomain matrix
121163602bcaSStefano Zampini 
121263602bcaSStefano Zampini    Collective
121363602bcaSStefano Zampini 
121463602bcaSStefano Zampini    Input Parameters:
121563602bcaSStefano Zampini +  pc - the preconditioning context
12160f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
12170f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in local ordering
121863602bcaSStefano Zampini 
121963602bcaSStefano Zampini    Level: intermediate
122063602bcaSStefano Zampini 
12210f202f7eSStefano Zampini    Notes:
12220f202f7eSStefano Zampini      n_is should be the same among processes. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
122363602bcaSStefano Zampini 
122463602bcaSStefano Zampini .seealso: PCBDDC
122563602bcaSStefano Zampini @*/
122663602bcaSStefano Zampini PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc,PetscInt n_is, IS ISForDofs[])
122763602bcaSStefano Zampini {
122863602bcaSStefano Zampini   PetscInt       i;
122963602bcaSStefano Zampini   PetscErrorCode ierr;
123063602bcaSStefano Zampini 
123163602bcaSStefano Zampini   PetscFunctionBegin;
123263602bcaSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
123363602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
123463602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
123563602bcaSStefano Zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
123663602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
123763602bcaSStefano Zampini   }
1238e71e7a71SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplittingLocal_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
123963602bcaSStefano Zampini   PetscFunctionReturn(0);
124063602bcaSStefano Zampini }
124163602bcaSStefano Zampini 
12429c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
12439c0446d6SStefano Zampini {
12449c0446d6SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
12459c0446d6SStefano Zampini   PetscInt       i;
124656282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
12479c0446d6SStefano Zampini   PetscErrorCode ierr;
12489c0446d6SStefano Zampini 
12499c0446d6SStefano Zampini   PetscFunctionBegin;
125056282151SStefano Zampini   if (pcbddc->n_ISForDofs == n_is) {
125156282151SStefano Zampini     for (i=0;i<n_is;i++) {
125256282151SStefano Zampini       PetscBool isequalt;
125356282151SStefano Zampini       ierr = ISEqual(ISForDofs[i],pcbddc->ISForDofs[i],&isequalt);CHKERRQ(ierr);
125456282151SStefano Zampini       if (!isequalt) break;
125556282151SStefano Zampini     }
125656282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
125756282151SStefano Zampini   }
125856282151SStefano Zampini   for (i=0;i<n_is;i++) {
125956282151SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
126056282151SStefano Zampini   }
1261da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
12629c0446d6SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
12639c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
12649c0446d6SStefano Zampini   }
1265d11ae9bbSstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
1266a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
126763602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
126863602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
126963602bcaSStefano Zampini   }
127063602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
127163602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = 0;
1272da1bb401SStefano Zampini   /* allocate space then set */
1273d02579f5SStefano Zampini   if (n_is) {
1274785e854fSJed Brown     ierr = PetscMalloc1(n_is,&pcbddc->ISForDofs);CHKERRQ(ierr);
1275d02579f5SStefano Zampini   }
12769c0446d6SStefano Zampini   for (i=0;i<n_is;i++) {
1277da1bb401SStefano Zampini     pcbddc->ISForDofs[i] = ISForDofs[i];
12789c0446d6SStefano Zampini   }
12799c0446d6SStefano Zampini   pcbddc->n_ISForDofs = n_is;
128063602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
128156282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
12829c0446d6SStefano Zampini   PetscFunctionReturn(0);
12839c0446d6SStefano Zampini }
12841e6b0712SBarry Smith 
12859c0446d6SStefano Zampini /*@
128663602bcaSStefano Zampini  PCBDDCSetDofsSplitting - Set index sets defining fields of the global matrix
12879c0446d6SStefano Zampini 
128863602bcaSStefano Zampini    Collective
12899c0446d6SStefano Zampini 
12909c0446d6SStefano Zampini    Input Parameters:
12919c0446d6SStefano Zampini +  pc - the preconditioning context
12920f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
12930f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in global ordering
12949c0446d6SStefano Zampini 
12959c0446d6SStefano Zampini    Level: intermediate
12969c0446d6SStefano Zampini 
12970f202f7eSStefano Zampini    Notes:
12980f202f7eSStefano Zampini      Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
12999c0446d6SStefano Zampini 
13009c0446d6SStefano Zampini .seealso: PCBDDC
13019c0446d6SStefano Zampini @*/
13029c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
13039c0446d6SStefano Zampini {
13042b510759SStefano Zampini   PetscInt       i;
13059c0446d6SStefano Zampini   PetscErrorCode ierr;
13069c0446d6SStefano Zampini 
13079c0446d6SStefano Zampini   PetscFunctionBegin;
13089c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
130963602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
13102b510759SStefano Zampini   for (i=0;i<n_is;i++) {
131163602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
1312a011d5a7Sstefano_zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
13132b510759SStefano Zampini   }
13149c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
13159c0446d6SStefano Zampini   PetscFunctionReturn(0);
13169c0446d6SStefano Zampini }
1317906d46d4SStefano Zampini 
1318534831adSStefano Zampini /*
1319534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
1320534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
13219c0446d6SStefano Zampini 
1322534831adSStefano Zampini    Input Parameter:
1323966d8056SPierre Jolivet +  pc - the preconditioner context
1324534831adSStefano Zampini 
1325534831adSStefano Zampini    Application Interface Routine: PCPreSolve()
1326534831adSStefano Zampini 
1327534831adSStefano Zampini    Notes:
1328534831adSStefano Zampini      The interface routine PCPreSolve() is not usually called directly by
1329534831adSStefano Zampini    the user, but instead is called by KSPSolve().
1330534831adSStefano Zampini */
1331534831adSStefano Zampini static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1332534831adSStefano Zampini {
1333534831adSStefano Zampini   PetscErrorCode ierr;
1334534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1335534831adSStefano Zampini   PC_IS          *pcis = (PC_IS*)(pc->data);
13363972b0daSStefano Zampini   Vec            used_vec;
13374df7a6bfSStefano Zampini   PetscBool      iscg = PETSC_FALSE, save_rhs = PETSC_TRUE, benign_correction_computed;
1338534831adSStefano Zampini 
1339534831adSStefano Zampini   PetscFunctionBegin;
13401f4df5f7SStefano Zampini   /* if we are working with CG, one dirichlet solve can be avoided during Krylov iterations */
134185c4d303SStefano Zampini   if (ksp) {
13424df7a6bfSStefano Zampini     PetscBool isgroppcg, ispipecg, ispipelcg, ispipecgrr;
13434df7a6bfSStefano Zampini 
134485c4d303SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPCG,&iscg);CHKERRQ(ierr);
134527b6a85dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPGROPPCG,&isgroppcg);CHKERRQ(ierr);
134627b6a85dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECG,&ispipecg);CHKERRQ(ierr);
13474df7a6bfSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECG,&ispipelcg);CHKERRQ(ierr);
1348f94e96cbSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECGRR,&ispipecgrr);CHKERRQ(ierr);
13494df7a6bfSStefano Zampini     iscg = (PetscBool)(iscg || isgroppcg || ispipecg || ispipelcg || ispipecgrr);
13503bf6e316SStefano Zampini     if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || !iscg || pc->mat != pc->pmat) {
135185c4d303SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
135285c4d303SStefano Zampini     }
135385c4d303SStefano Zampini   }
13543bf6e316SStefano Zampini   if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || pc->mat != pc->pmat) {
1355fc17d649SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
1356fc17d649SStefano Zampini   }
13571f4df5f7SStefano Zampini 
135885c4d303SStefano Zampini   /* Creates parallel work vectors used in presolve */
135962a6ff1dSStefano Zampini   if (!pcbddc->original_rhs) {
136062a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
136162a6ff1dSStefano Zampini   }
136262a6ff1dSStefano Zampini   if (!pcbddc->temp_solution) {
136362a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr);
136462a6ff1dSStefano Zampini   }
13658d00608fSStefano Zampini 
136627b6a85dSStefano Zampini   pcbddc->temp_solution_used = PETSC_FALSE;
13673972b0daSStefano Zampini   if (x) {
13683972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);
13693972b0daSStefano Zampini     used_vec = x;
13708d00608fSStefano Zampini   } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */
13713972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr);
13723972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
13733972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
137427b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
1375266e20e9SStefano Zampini     ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
1376266e20e9SStefano Zampini     save_rhs = PETSC_FALSE;
1377266e20e9SStefano Zampini     pcbddc->eliminate_dirdofs = PETSC_TRUE;
13783972b0daSStefano Zampini   }
13798efcfb23SStefano Zampini 
13808efcfb23SStefano Zampini   /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */
13813972b0daSStefano Zampini   if (ksp) {
1382a0cb1b98SStefano Zampini     /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */
13838efcfb23SStefano Zampini     ierr = KSPGetInitialGuessNonzero(ksp,&pcbddc->ksp_guess_nonzero);CHKERRQ(ierr);
13848efcfb23SStefano Zampini     if (!pcbddc->ksp_guess_nonzero) {
13853972b0daSStefano Zampini       ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
13863972b0daSStefano Zampini     }
13873972b0daSStefano Zampini   }
13883308cffdSStefano Zampini 
13898d00608fSStefano Zampini   pcbddc->rhs_change = PETSC_FALSE;
13903972b0daSStefano Zampini   /* Take into account zeroed rows -> change rhs and store solution removed */
139170c64980SStefano Zampini   if (rhs && pcbddc->eliminate_dirdofs) {
13923975b054SStefano Zampini     IS dirIS = NULL;
13933975b054SStefano Zampini 
1394a07ea27aSStefano Zampini     /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */
13953975b054SStefano Zampini     ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
13963975b054SStefano Zampini     if (dirIS) {
1397906d46d4SStefano Zampini       Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
1398785d1243SStefano Zampini       PetscInt          dirsize,i,*is_indices;
13992b095fd8SStefano Zampini       PetscScalar       *array_x;
14002b095fd8SStefano Zampini       const PetscScalar *array_diagonal;
1401785d1243SStefano Zampini 
14023972b0daSStefano Zampini       ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr);
14033972b0daSStefano Zampini       ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr);
1404e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1405e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1406e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1407e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
140882ba6b80SStefano Zampini       ierr = ISGetLocalSize(dirIS,&dirsize);CHKERRQ(ierr);
14093972b0daSStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
14102b095fd8SStefano Zampini       ierr = VecGetArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
14113972b0daSStefano Zampini       ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
14122fa5cd67SKarl Rupp       for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
14133972b0daSStefano Zampini       ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
14142b095fd8SStefano Zampini       ierr = VecRestoreArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
14153972b0daSStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
1416e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1417e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
14188d00608fSStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
14191b968477SStefano Zampini       ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
14208efcfb23SStefano Zampini     }
1421a07ea27aSStefano Zampini   }
1422b76ba322SStefano Zampini 
14238efcfb23SStefano Zampini   /* remove the computed solution or the initial guess from the rhs */
14248d00608fSStefano Zampini   if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero)) {
142527b6a85dSStefano Zampini     /* save the original rhs */
142627b6a85dSStefano Zampini     if (save_rhs) {
142727b6a85dSStefano Zampini       ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
142827b6a85dSStefano Zampini       save_rhs = PETSC_FALSE;
14298d00608fSStefano Zampini     }
14308d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
14313972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
143227b6a85dSStefano Zampini     ierr = MatMultAdd(pc->mat,used_vec,pcbddc->original_rhs,rhs);CHKERRQ(ierr);
14333972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
14348efcfb23SStefano Zampini     ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr);
143527b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
14367acc28cbSStefano Zampini     if (ksp) {
14377acc28cbSStefano Zampini       ierr = KSPSetInitialGuessNonzero(ksp,PETSC_FALSE);CHKERRQ(ierr);
14387acc28cbSStefano Zampini     }
14393308cffdSStefano Zampini   }
14408efcfb23SStefano Zampini   ierr = VecDestroy(&used_vec);CHKERRQ(ierr);
1441b76ba322SStefano Zampini 
1442fc17d649SStefano Zampini   /* compute initial vector in benign space if needed
144327b6a85dSStefano Zampini      and remove non-benign solution from the rhs */
144427b6a85dSStefano Zampini   benign_correction_computed = PETSC_FALSE;
144508af2428SStefano Zampini   if (rhs && pcbddc->benign_compute_correction && (pcbddc->benign_have_null || pcbddc->benign_apply_coarse_only)) {
14461f4df5f7SStefano Zampini     /* compute u^*_h using ideas similar to those in Xuemin Tu's PhD thesis (see Section 4.8.1)
14471f4df5f7SStefano Zampini        Recursively apply BDDC in the multilevel case */
14480369aaf7SStefano Zampini     if (!pcbddc->benign_vec) {
14490369aaf7SStefano Zampini       ierr = VecDuplicate(rhs,&pcbddc->benign_vec);CHKERRQ(ierr);
14500369aaf7SStefano Zampini     }
1451c69e9cc1SStefano Zampini     /* keep applying coarse solver unless we no longer have benign subdomains */
1452c69e9cc1SStefano Zampini     pcbddc->benign_apply_coarse_only = pcbddc->benign_have_null ? PETSC_TRUE : PETSC_FALSE;
145327b6a85dSStefano Zampini     if (!pcbddc->benign_skip_correction) {
14541dd7afcfSStefano Zampini       ierr = PCApply_BDDC(pc,rhs,pcbddc->benign_vec);CHKERRQ(ierr);
14553bca92a6SStefano Zampini       benign_correction_computed = PETSC_TRUE;
14561f4df5f7SStefano Zampini       if (pcbddc->temp_solution_used) {
14571f4df5f7SStefano Zampini         ierr = VecAXPY(pcbddc->temp_solution,1.0,pcbddc->benign_vec);CHKERRQ(ierr);
14581f4df5f7SStefano Zampini       }
14591f4df5f7SStefano Zampini       ierr = VecScale(pcbddc->benign_vec,-1.0);CHKERRQ(ierr);
146027b6a85dSStefano Zampini       /* store the original rhs if not done earlier */
146127b6a85dSStefano Zampini       if (save_rhs) {
146227b6a85dSStefano Zampini         ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
146392e3dcfbSStefano Zampini       }
146427b6a85dSStefano Zampini       if (pcbddc->rhs_change) {
14650369aaf7SStefano Zampini         ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,rhs,rhs);CHKERRQ(ierr);
146627b6a85dSStefano Zampini       } else {
146727b6a85dSStefano Zampini         ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,pcbddc->original_rhs,rhs);CHKERRQ(ierr);
146827b6a85dSStefano Zampini       }
14690369aaf7SStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
147027b6a85dSStefano Zampini     }
147127b6a85dSStefano Zampini     pcbddc->benign_apply_coarse_only = PETSC_FALSE;
14724df7a6bfSStefano Zampini   } else {
14734df7a6bfSStefano Zampini     ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
14740369aaf7SStefano Zampini   }
14752d4c4fecSStefano Zampini 
14762d4c4fecSStefano Zampini   /* dbg output */
1477a198735bSStefano Zampini   if (pcbddc->dbg_flag && benign_correction_computed) {
14781f4df5f7SStefano Zampini     Vec v;
1479c69e9cc1SStefano Zampini 
14801f4df5f7SStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&v);CHKERRQ(ierr);
1481c69e9cc1SStefano Zampini     if (pcbddc->ChangeOfBasisMatrix) {
14821f4df5f7SStefano Zampini       ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,v);CHKERRQ(ierr);
1483c69e9cc1SStefano Zampini     } else {
1484c69e9cc1SStefano Zampini       ierr = VecCopy(rhs,v);CHKERRQ(ierr);
1485c69e9cc1SStefano Zampini     }
14861f4df5f7SStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,v,PETSC_TRUE);CHKERRQ(ierr);
1487e0fe2d75SToby Isaac     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"LEVEL %D: is the correction benign?\n",pcbddc->current_level);CHKERRQ(ierr);
1488c69e9cc1SStefano Zampini     ierr = PetscScalarView(pcbddc->benign_n,pcbddc->benign_p0,pcbddc->dbg_viewer);CHKERRQ(ierr);
1489c69e9cc1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
14901f4df5f7SStefano Zampini     ierr = VecDestroy(&v);CHKERRQ(ierr);
14911f4df5f7SStefano Zampini   }
14920369aaf7SStefano Zampini 
14930369aaf7SStefano Zampini   /* set initial guess if using PCG */
14948ae0ca82SStefano Zampini   pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
14950369aaf7SStefano Zampini   if (x && pcbddc->use_exact_dirichlet_trick) {
14960369aaf7SStefano Zampini     ierr = VecSet(x,0.0);CHKERRQ(ierr);
14971dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
149827b6a85dSStefano Zampini       if (benign_correction_computed) { /* we have already saved the changed rhs */
14998860a134SJunchao Zhang         ierr = VecLockReadPop(pcis->vec1_global);CHKERRQ(ierr);
15001dd7afcfSStefano Zampini       } else {
15011dd7afcfSStefano Zampini         ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,pcis->vec1_global);CHKERRQ(ierr);
15021dd7afcfSStefano Zampini       }
15031dd7afcfSStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15041dd7afcfSStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15051dd7afcfSStefano Zampini     } else {
15060369aaf7SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15070369aaf7SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15081dd7afcfSStefano Zampini     }
150955c176c0SStefano Zampini     ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr);
15100369aaf7SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
151155c176c0SStefano Zampini     ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr);
1512c0decd05SBarry Smith     ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D);CHKERRQ(ierr);
15131dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
15141dd7afcfSStefano Zampini       ierr = VecSet(pcis->vec1_global,0.);CHKERRQ(ierr);
15151dd7afcfSStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15161dd7afcfSStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15171dd7afcfSStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x);CHKERRQ(ierr);
15181dd7afcfSStefano Zampini     } else {
15190369aaf7SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15200369aaf7SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15211dd7afcfSStefano Zampini     }
15220369aaf7SStefano Zampini     if (ksp) {
15230369aaf7SStefano Zampini       ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
15240369aaf7SStefano Zampini     }
15258ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_TRUE;
1526266e20e9SStefano Zampini   } else if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior && benign_correction_computed && pcbddc->use_exact_dirichlet_trick) {
15278860a134SJunchao Zhang     ierr = VecLockReadPop(pcis->vec1_global);CHKERRQ(ierr);
15280369aaf7SStefano Zampini   }
1529534831adSStefano Zampini   PetscFunctionReturn(0);
1530534831adSStefano Zampini }
1531906d46d4SStefano Zampini 
1532534831adSStefano Zampini /*
1533534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
1534534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
1535534831adSStefano Zampini 
1536534831adSStefano Zampini    Input Parameter:
1537966d8056SPierre Jolivet +  pc - the preconditioner context
1538534831adSStefano Zampini 
1539534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
1540534831adSStefano Zampini 
1541534831adSStefano Zampini    Notes:
1542534831adSStefano Zampini      The interface routine PCPostSolve() is not usually called directly by
1543534831adSStefano Zampini      the user, but instead is called by KSPSolve().
1544534831adSStefano Zampini */
1545534831adSStefano Zampini static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1546534831adSStefano Zampini {
1547534831adSStefano Zampini   PetscErrorCode ierr;
1548534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1549534831adSStefano Zampini 
1550534831adSStefano Zampini   PetscFunctionBegin;
15513972b0daSStefano Zampini   /* add solution removed in presolve */
15526bcfc461SStefano Zampini   if (x && pcbddc->rhs_change) {
155327b6a85dSStefano Zampini     if (pcbddc->temp_solution_used) {
15543425bc38SStefano Zampini       ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr);
1555af140850Sstefano_zampini     } else if (pcbddc->benign_compute_correction && pcbddc->benign_vec) {
155627b6a85dSStefano Zampini       ierr = VecAXPY(x,-1.0,pcbddc->benign_vec);CHKERRQ(ierr);
15573425bc38SStefano Zampini     }
1558af140850Sstefano_zampini     /* restore to original state (not for FETI-DP) */
1559af140850Sstefano_zampini     if (ksp) pcbddc->temp_solution_used = PETSC_FALSE;
156027b6a85dSStefano Zampini   }
156127b6a85dSStefano Zampini 
1562266e20e9SStefano Zampini   /* restore rhs to its original state (not needed for FETI-DP) */
15638d00608fSStefano Zampini   if (rhs && pcbddc->rhs_change) {
156427b6a85dSStefano Zampini     ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
15658d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_FALSE;
1566af140850Sstefano_zampini   }
15678efcfb23SStefano Zampini   /* restore ksp guess state */
15688efcfb23SStefano Zampini   if (ksp) {
15698efcfb23SStefano Zampini     ierr = KSPSetInitialGuessNonzero(ksp,pcbddc->ksp_guess_nonzero);CHKERRQ(ierr);
15708ae0ca82SStefano Zampini     /* reset flag for exact dirichlet trick */
15718ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
1572af140850Sstefano_zampini   }
1573534831adSStefano Zampini   PetscFunctionReturn(0);
1574534831adSStefano Zampini }
1575af140850Sstefano_zampini 
15760c7d97c5SJed Brown /*
15770c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
15780c7d97c5SJed Brown                   by setting data structures and options.
15790c7d97c5SJed Brown 
15800c7d97c5SJed Brown    Input Parameter:
158153cdbc3dSStefano Zampini +  pc - the preconditioner context
15820c7d97c5SJed Brown 
15830c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
15840c7d97c5SJed Brown 
15850c7d97c5SJed Brown    Notes:
15860c7d97c5SJed Brown      The interface routine PCSetUp() is not usually called directly by
15870c7d97c5SJed Brown      the user, but instead is called by PCApply() if necessary.
15880c7d97c5SJed Brown */
158953cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
15900c7d97c5SJed Brown {
15910c7d97c5SJed Brown   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1592c703fcc7SStefano Zampini   PCBDDCSubSchurs sub_schurs;
15935e8657edSStefano Zampini   Mat_IS*         matis;
159408122e43SStefano Zampini   MatNullSpace    nearnullspace;
159535509ce9Sstefano_zampini   Mat             lA;
159635509ce9Sstefano_zampini   IS              lP,zerodiag = NULL;
159791e8d312SStefano Zampini   PetscInt        nrows,ncols;
159886bfa4cfSStefano Zampini   PetscMPIInt     size;
1599c703fcc7SStefano Zampini   PetscBool       computesubschurs;
16008de1fae6SStefano Zampini   PetscBool       computeconstraintsmatrix;
16013b03f7bbSStefano Zampini   PetscBool       new_nearnullspace_provided,ismatis,rl;
1602c703fcc7SStefano Zampini   PetscErrorCode  ierr;
16030c7d97c5SJed Brown 
16040c7d97c5SJed Brown   PetscFunctionBegin;
16055e8657edSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATIS,&ismatis);CHKERRQ(ierr);
16062c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!ismatis,PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner requires matrix of type MATIS");
160791e8d312SStefano Zampini   ierr = MatGetSize(pc->pmat,&nrows,&ncols);CHKERRQ(ierr);
16082c71b3e2SJacob Faibussowitsch   PetscCheckFalse(nrows != ncols,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCBDDC preconditioner requires a square preconditioning matrix");
1609ffc4695bSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRMPI(ierr);
161086bfa4cfSStefano Zampini 
16115e8657edSStefano Zampini   matis = (Mat_IS*)pc->pmat->data;
1612f4ddd8eeSStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */
16133b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
161471582508SStefano Zampini      Also, BDDC builds its own KSP for the Dirichlet problem */
16153b03f7bbSStefano Zampini   rl = pcbddc->recompute_topography;
16163b03f7bbSStefano Zampini   if (!pc->setupcalled || pc->flag == DIFFERENT_NONZERO_PATTERN) rl = PETSC_TRUE;
1617820f2d46SBarry Smith   ierr = MPIU_Allreduce(&rl,&pcbddc->recompute_topography,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr);
1618c83e1ba7SStefano Zampini   if (pcbddc->recompute_topography) {
1619c83e1ba7SStefano Zampini     pcbddc->graphanalyzed    = PETSC_FALSE;
1620c83e1ba7SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1621c83e1ba7SStefano Zampini   } else {
16228de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_FALSE;
1623c83e1ba7SStefano Zampini   }
1624b087196eSStefano Zampini 
1625b087196eSStefano Zampini   /* check parameters' compatibility */
1626b7ab4a40SStefano Zampini   if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE;
1627bd2a564bSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_threshold[0] != 0.0 || pcbddc->adaptive_threshold[1] != 0.0);
162886bfa4cfSStefano Zampini   pcbddc->use_deluxe_scaling   = (PetscBool)(pcbddc->use_deluxe_scaling && size > 1);
162986bfa4cfSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_selection && size > 1);
1630bf3a8328SStefano Zampini   pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined);
1631862806e4SStefano Zampini   if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE;
1632862806e4SStefano Zampini 
16335a95e1ceSStefano Zampini   computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling);
163416909a7fSStefano Zampini 
163571582508SStefano Zampini   /* activate all connected components if the netflux has been requested */
1636bb05f991SStefano Zampini   if (pcbddc->compute_nonetflux) {
1637bb05f991SStefano Zampini     pcbddc->use_vertices = PETSC_TRUE;
1638bb05f991SStefano Zampini     pcbddc->use_edges    = PETSC_TRUE;
1639bb05f991SStefano Zampini     pcbddc->use_faces    = PETSC_TRUE;
1640bb05f991SStefano Zampini   }
1641bb05f991SStefano Zampini 
1642f4ddd8eeSStefano Zampini   /* Get stdout for dbg */
164370cf5478SStefano Zampini   if (pcbddc->dbg_flag) {
164470cf5478SStefano Zampini     if (!pcbddc->dbg_viewer) {
164558a03d70SStefano Zampini       pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc));
1646f4ddd8eeSStefano Zampini     }
1647d9869140SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
164858a03d70SStefano Zampini     ierr = PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
1649f4ddd8eeSStefano Zampini   }
1650f4ddd8eeSStefano Zampini 
1651c703fcc7SStefano Zampini   /* process topology information */
165243371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_Topology[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
165371582508SStefano Zampini   if (pcbddc->recompute_topography) {
165471582508SStefano Zampini     ierr = PCBDDCComputeLocalTopologyInfo(pc);CHKERRQ(ierr);
1655c703fcc7SStefano Zampini     if (pcbddc->discretegradient) {
1656a13144ffSStefano Zampini       ierr = PCBDDCNedelecSupport(pc);CHKERRQ(ierr);
1657a13144ffSStefano Zampini     }
1658c703fcc7SStefano Zampini   }
16594f819b78SStefano Zampini   if (pcbddc->corner_selected) pcbddc->use_vertices = PETSC_TRUE;
1660a13144ffSStefano Zampini 
1661c703fcc7SStefano Zampini   /* change basis if requested by the user */
16625e8657edSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) {
16635e8657edSStefano Zampini     /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */
16645e8657edSStefano Zampini     pcbddc->use_change_of_basis = PETSC_FALSE;
16655e8657edSStefano Zampini     ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
16665e8657edSStefano Zampini   } else {
1667b96c3477SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
16685e8657edSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
16695e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
1670d16cbb6bSStefano Zampini   }
1671d16cbb6bSStefano Zampini 
16724f1b2e48SStefano Zampini   /*
1673c703fcc7SStefano Zampini      Compute change of basis on local pressures (aka zerodiag dofs) with the benign trick
16744f1b2e48SStefano Zampini      This should come earlier then PCISSetUp for extracting the correct subdomain matrices
16754f1b2e48SStefano Zampini   */
16761dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
1677d16cbb6bSStefano Zampini   if (pcbddc->benign_saddle_point) {
16789f47a83aSStefano Zampini     PC_IS* pcis = (PC_IS*)pc->data;
16799f47a83aSStefano Zampini 
168005b28244SStefano Zampini     if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE;
16813b03f7bbSStefano Zampini     /* detect local saddle point and change the basis in pcbddc->local_mat */
16823b03f7bbSStefano Zampini     ierr = PCBDDCBenignDetectSaddlePoint(pc,(PetscBool)(!pcbddc->recompute_topography),&zerodiag);CHKERRQ(ierr);
1683a3df083aSStefano Zampini     /* pop B0 mat from local mat */
1684c263805aSStefano Zampini     ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
16851dd7afcfSStefano Zampini     /* give pcis a hint to not reuse submatrices during PCISCreate */
16861dd7afcfSStefano Zampini     if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) {
16871dd7afcfSStefano Zampini       if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) {
16881dd7afcfSStefano Zampini         pcis->reusesubmatrices = PETSC_FALSE;
16891dd7afcfSStefano Zampini       } else {
1690a3df083aSStefano Zampini         pcis->reusesubmatrices = PETSC_TRUE;
16911dd7afcfSStefano Zampini       }
1692a3df083aSStefano Zampini     } else {
16939f47a83aSStefano Zampini       pcis->reusesubmatrices = PETSC_FALSE;
1694674ae819SStefano Zampini     }
1695a3df083aSStefano Zampini   }
169627b6a85dSStefano Zampini 
16978037d520SStefano Zampini   /* propagate relevant information */
169806a4e24aSStefano Zampini   if (matis->A->symmetric_set) {
169906a4e24aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
170006a4e24aSStefano Zampini   }
170106a4e24aSStefano Zampini   if (matis->A->spd_set) {
170206a4e24aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SPD,matis->A->spd);CHKERRQ(ierr);
170306a4e24aSStefano Zampini   }
1704e496cd5dSStefano Zampini 
17055e8657edSStefano Zampini   /* Set up all the "iterative substructuring" common block without computing solvers */
17065e8657edSStefano Zampini   {
17075e8657edSStefano Zampini     Mat temp_mat;
17085e8657edSStefano Zampini 
17095e8657edSStefano Zampini     temp_mat = matis->A;
17105e8657edSStefano Zampini     matis->A = pcbddc->local_mat;
1711d9869140SStefano Zampini     ierr = PCISSetUp(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
17125e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
17135e8657edSStefano Zampini     matis->A = temp_mat;
17145e8657edSStefano Zampini   }
1715684f6988SStefano Zampini 
171681d14e9dSStefano Zampini   /* Analyze interface */
171764ac59b8SStefano Zampini   if (!pcbddc->graphanalyzed) {
1718674ae819SStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
17198de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1720345ecf6cSStefano Zampini     if (pcbddc->adaptive_selection && !pcbddc->use_deluxe_scaling && !pcbddc->mat_graph->twodim) {
17214247aa23Sstefano_zampini       SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot compute the adaptive primal space for a problem with 3D edges without deluxe scaling");
1722345ecf6cSStefano Zampini     }
1723a198735bSStefano Zampini     if (pcbddc->compute_nonetflux) {
1724669cc0f4SStefano Zampini       MatNullSpace nnfnnsp;
1725669cc0f4SStefano Zampini 
17262c71b3e2SJacob Faibussowitsch       PetscCheckFalse(!pcbddc->divudotp,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Missing divudotp operator");
17278ae0ca82SStefano Zampini       ierr = PCBDDCComputeNoNetFlux(pc->pmat,pcbddc->divudotp,pcbddc->divudotp_trans,pcbddc->divudotp_vl2l,pcbddc->mat_graph,&nnfnnsp);CHKERRQ(ierr);
172871582508SStefano Zampini       /* TODO what if a nearnullspace is already attached? */
17298037d520SStefano Zampini       if (nnfnnsp) {
1730669cc0f4SStefano Zampini         ierr = MatSetNearNullSpace(pc->pmat,nnfnnsp);CHKERRQ(ierr);
1731669cc0f4SStefano Zampini         ierr = MatNullSpaceDestroy(&nnfnnsp);CHKERRQ(ierr);
1732669cc0f4SStefano Zampini       }
1733674ae819SStefano Zampini     }
17348037d520SStefano Zampini   }
173543371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_Topology[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
1736fb8d54d4SStefano Zampini 
17375408967cSStefano Zampini   /* check existence of a divergence free extension, i.e.
17385408967cSStefano Zampini      b(v_I,p_0) = 0 for all v_I (raise error if not).
17395408967cSStefano Zampini      Also, check that PCBDDCBenignGetOrSetP0 works */
1740ff1f7e73Sstefano_zampini   if (pcbddc->benign_saddle_point && pcbddc->dbg_flag > 1) {
17415408967cSStefano Zampini     ierr = PCBDDCBenignCheck(pc,zerodiag);CHKERRQ(ierr);
174209f581a4SStefano Zampini   }
17434f1b2e48SStefano Zampini   ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
174406f24817SStefano Zampini 
1745b96c3477SStefano Zampini   /* Setup local dirichlet solver ksp_D and sub_schurs solvers */
1746c703fcc7SStefano Zampini   if (computesubschurs && pcbddc->recompute_topography) {
174708122e43SStefano Zampini     ierr = PCBDDCInitSubSchurs(pc);CHKERRQ(ierr);
1748b1b3d7a2SStefano Zampini   }
17499d54b7f4SStefano Zampini   /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/
17509d54b7f4SStefano Zampini   if (!pcbddc->use_deluxe_scaling) {
17519d54b7f4SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
17529d54b7f4SStefano Zampini   }
1753c703fcc7SStefano Zampini 
1754c703fcc7SStefano Zampini   /* finish setup solvers and do adaptive selection of constraints */
1755b334f244SStefano Zampini   sub_schurs = pcbddc->sub_schurs;
1756b334f244SStefano Zampini   if (sub_schurs && sub_schurs->schur_explicit) {
17572070dbb6SStefano Zampini     if (computesubschurs) {
175808122e43SStefano Zampini       ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
17592070dbb6SStefano Zampini     }
1760d5574798SStefano Zampini     ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
1761d5574798SStefano Zampini   } else {
1762d5574798SStefano Zampini     ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
17632070dbb6SStefano Zampini     if (computesubschurs) {
1764d5574798SStefano Zampini       ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
1765d5574798SStefano Zampini     }
17662070dbb6SStefano Zampini   }
176708122e43SStefano Zampini   if (pcbddc->adaptive_selection) {
176808122e43SStefano Zampini     ierr = PCBDDCAdaptiveSelection(pc);CHKERRQ(ierr);
17698de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1770b7eb3628SStefano Zampini   }
1771684f6988SStefano Zampini 
1772f4ddd8eeSStefano Zampini   /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */
1773fb8d54d4SStefano Zampini   new_nearnullspace_provided = PETSC_FALSE;
1774f4ddd8eeSStefano Zampini   ierr = MatGetNearNullSpace(pc->pmat,&nearnullspace);CHKERRQ(ierr);
1775f4ddd8eeSStefano Zampini   if (pcbddc->onearnullspace) { /* already used nearnullspace */
1776f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* near null space attached to mat has been destroyed */
1777f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1778f4ddd8eeSStefano Zampini     } else {
1779f4ddd8eeSStefano Zampini       /* determine if the two nullspaces are different (should be lightweight) */
1780f4ddd8eeSStefano Zampini       if (nearnullspace != pcbddc->onearnullspace) {
1781f4ddd8eeSStefano Zampini         new_nearnullspace_provided = PETSC_TRUE;
1782165b64e2SStefano Zampini       } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */
1783f4ddd8eeSStefano Zampini         PetscInt         i;
1784165b64e2SStefano Zampini         const Vec        *nearnullvecs;
1785165b64e2SStefano Zampini         PetscObjectState state;
1786165b64e2SStefano Zampini         PetscInt         nnsp_size;
1787165b64e2SStefano Zampini         ierr = MatNullSpaceGetVecs(nearnullspace,NULL,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
1788f4ddd8eeSStefano Zampini         for (i=0;i<nnsp_size;i++) {
1789f4ddd8eeSStefano Zampini           ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&state);CHKERRQ(ierr);
1790165b64e2SStefano Zampini           if (pcbddc->onearnullvecs_state[i] != state) {
1791f4ddd8eeSStefano Zampini             new_nearnullspace_provided = PETSC_TRUE;
1792f4ddd8eeSStefano Zampini             break;
1793f4ddd8eeSStefano Zampini           }
1794f4ddd8eeSStefano Zampini         }
1795f4ddd8eeSStefano Zampini       }
1796f4ddd8eeSStefano Zampini     }
1797f4ddd8eeSStefano Zampini   } else {
1798f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* both nearnullspaces are null */
1799f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_FALSE;
1800f4ddd8eeSStefano Zampini     } else { /* nearnullspace attached later */
1801f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1802f4ddd8eeSStefano Zampini     }
1803f4ddd8eeSStefano Zampini   }
1804f4ddd8eeSStefano Zampini 
1805f4ddd8eeSStefano Zampini   /* Setup constraints and related work vectors */
1806727cdba6SStefano Zampini   /* reset primal space flags */
180743371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_LocalWork[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
1808f4ddd8eeSStefano Zampini   pcbddc->new_primal_space = PETSC_FALSE;
1809727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_FALSE;
18108de1fae6SStefano Zampini   if (computeconstraintsmatrix || new_nearnullspace_provided) {
1811727cdba6SStefano Zampini     /* It also sets the primal space flags */
1812674ae819SStefano Zampini     ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr);
18139543d0ffSStefano Zampini   }
1814e7b262bdSStefano Zampini   /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */
1815f4ddd8eeSStefano Zampini   ierr = PCBDDCSetUpLocalWorkVectors(pc);CHKERRQ(ierr);
18165e8657edSStefano Zampini 
18175e8657edSStefano Zampini   if (pcbddc->use_change_of_basis) {
18185e8657edSStefano Zampini     PC_IS *pcis = (PC_IS*)(pc->data);
18195e8657edSStefano Zampini 
18205e8657edSStefano Zampini     ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
18214f1b2e48SStefano Zampini     if (pcbddc->benign_change) {
18221dd7afcfSStefano Zampini       ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
1823c263805aSStefano Zampini       /* pop B0 from pcbddc->local_mat */
1824c263805aSStefano Zampini       ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
1825c263805aSStefano Zampini     }
18265e8657edSStefano Zampini     /* get submatrices */
18275e8657edSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
18285e8657edSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
18295e8657edSStefano Zampini     ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);
18307dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB);CHKERRQ(ierr);
18317dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr);
18327dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr);
18333975b054SStefano Zampini     /* set flag in pcis to not reuse submatrices during PCISCreate */
18343975b054SStefano Zampini     pcis->reusesubmatrices = PETSC_FALSE;
18359c6a02ceSStefano Zampini   } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) {
1836b96c3477SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
18375e8657edSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
18385e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
18395e8657edSStefano Zampini   }
184035509ce9Sstefano_zampini 
184135509ce9Sstefano_zampini   /* interface pressure block row for B_C */
184235509ce9Sstefano_zampini   ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP" ,(PetscObject*)&lP);CHKERRQ(ierr);
184335509ce9Sstefano_zampini   ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA);CHKERRQ(ierr);
184435509ce9Sstefano_zampini   if (lA && lP) {
184535509ce9Sstefano_zampini     PC_IS*    pcis = (PC_IS*)pc->data;
184635509ce9Sstefano_zampini     Mat       B_BI,B_BB,Bt_BI,Bt_BB;
184735509ce9Sstefano_zampini     PetscBool issym;
184835509ce9Sstefano_zampini     ierr = MatIsSymmetric(lA,PETSC_SMALL,&issym);CHKERRQ(ierr);
18496cc1294bSstefano_zampini     if (issym) {
18507dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI);CHKERRQ(ierr);
18517dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB);CHKERRQ(ierr);
185235509ce9Sstefano_zampini       ierr = MatCreateTranspose(B_BI,&Bt_BI);CHKERRQ(ierr);
185335509ce9Sstefano_zampini       ierr = MatCreateTranspose(B_BB,&Bt_BB);CHKERRQ(ierr);
185435509ce9Sstefano_zampini     } else {
18557dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI);CHKERRQ(ierr);
18567dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB);CHKERRQ(ierr);
18577dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,pcis->is_I_local,lP,MAT_INITIAL_MATRIX,&Bt_BI);CHKERRQ(ierr);
18587dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,pcis->is_B_local,lP,MAT_INITIAL_MATRIX,&Bt_BB);CHKERRQ(ierr);
185935509ce9Sstefano_zampini     }
186035509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BI",(PetscObject)B_BI);CHKERRQ(ierr);
186135509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BB",(PetscObject)B_BB);CHKERRQ(ierr);
186235509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BI",(PetscObject)Bt_BI);CHKERRQ(ierr);
186335509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BB",(PetscObject)Bt_BB);CHKERRQ(ierr);
186435509ce9Sstefano_zampini     ierr = MatDestroy(&B_BI);CHKERRQ(ierr);
186535509ce9Sstefano_zampini     ierr = MatDestroy(&B_BB);CHKERRQ(ierr);
186635509ce9Sstefano_zampini     ierr = MatDestroy(&Bt_BI);CHKERRQ(ierr);
186735509ce9Sstefano_zampini     ierr = MatDestroy(&Bt_BB);CHKERRQ(ierr);
186835509ce9Sstefano_zampini   }
186943371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_LocalWork[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
187035509ce9Sstefano_zampini 
1871b96c3477SStefano Zampini   /* SetUp coarse and local Neumann solvers */
187299cc7994SStefano Zampini   ierr = PCBDDCSetUpSolvers(pc);CHKERRQ(ierr);
1873b96c3477SStefano Zampini   /* SetUp Scaling operator */
18749d54b7f4SStefano Zampini   if (pcbddc->use_deluxe_scaling) {
1875674ae819SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
18760c7d97c5SJed Brown   }
1877c703fcc7SStefano Zampini 
18781dd7afcfSStefano Zampini   /* mark topography as done */
187956282151SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
18800369aaf7SStefano Zampini 
18811dd7afcfSStefano Zampini   /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */
18821dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_FALSE);CHKERRQ(ierr);
18831dd7afcfSStefano Zampini 
188458a03d70SStefano Zampini   if (pcbddc->dbg_flag) {
188558a03d70SStefano Zampini     ierr = PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
1886d9869140SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
18872b510759SStefano Zampini   }
18880c7d97c5SJed Brown   PetscFunctionReturn(0);
18890c7d97c5SJed Brown }
18900c7d97c5SJed Brown 
18910c7d97c5SJed Brown /*
189250efa1b5SStefano Zampini    PCApply_BDDC - Applies the BDDC operator to a vector.
18930c7d97c5SJed Brown 
18940c7d97c5SJed Brown    Input Parameters:
18950f202f7eSStefano Zampini +  pc - the preconditioner context
18960f202f7eSStefano Zampini -  r - input vector (global)
18970c7d97c5SJed Brown 
18980c7d97c5SJed Brown    Output Parameter:
18990c7d97c5SJed Brown .  z - output vector (global)
19000c7d97c5SJed Brown 
19010c7d97c5SJed Brown    Application Interface Routine: PCApply()
19020c7d97c5SJed Brown  */
190353cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
19040c7d97c5SJed Brown {
19050c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
19060c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1907b3338236SStefano Zampini   Mat               lA = NULL;
1908b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
19090c7d97c5SJed Brown   PetscErrorCode    ierr;
19103b03a366Sstefano_zampini   const PetscScalar one = 1.0;
19113b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
19122617d88aSStefano Zampini   const PetscScalar zero = 0.0;
19130c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
19140c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
1915b097fa66SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */
19160c7d97c5SJed Brown 
19170c7d97c5SJed Brown   PetscFunctionBegin;
1918f3d41395Sstefano_zampini   ierr = PetscCitationsRegister(citation,&cited);CHKERRQ(ierr);
1919b3338236SStefano Zampini   if (pcbddc->switch_static) {
1920b3338236SStefano Zampini     ierr = MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat,&lA);CHKERRQ(ierr);
1921b3338236SStefano Zampini   }
1922b3338236SStefano Zampini 
19231dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
19241dd7afcfSStefano Zampini     Vec swap;
192527b6a85dSStefano Zampini 
192627b6a85dSStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
19271dd7afcfSStefano Zampini     swap = pcbddc->work_change;
19281dd7afcfSStefano Zampini     pcbddc->work_change = r;
19291dd7afcfSStefano Zampini     r = swap;
19301dd7afcfSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
19319cc2a9b1Sstefano_zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) {
19321dd7afcfSStefano Zampini       ierr = VecCopy(r,pcis->vec1_global);CHKERRQ(ierr);
19338860a134SJunchao Zhang       ierr = VecLockReadPush(pcis->vec1_global);CHKERRQ(ierr);
19341dd7afcfSStefano Zampini     }
19351dd7afcfSStefano Zampini   }
193627b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
1937015636ebSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
1938efc2fbd9SStefano Zampini   }
1939bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET && !pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1940b097fa66SStefano Zampini     ierr = VecCopy(r,z);CHKERRQ(ierr);
19410c7d97c5SJed Brown     /* First Dirichlet solve */
19420c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19430c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19440c7d97c5SJed Brown     /*
19450c7d97c5SJed Brown       Assembling right hand side for BDDC operator
1946b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
1947674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
19480c7d97c5SJed Brown     */
1949b097fa66SStefano Zampini     if (n_D) {
195055c176c0SStefano Zampini       ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr);
1951b097fa66SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
195255c176c0SStefano Zampini       ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr);
1953c0decd05SBarry Smith       ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D);CHKERRQ(ierr);
19540c7d97c5SJed Brown       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
195516909a7fSStefano Zampini       if (pcbddc->switch_static) {
195616909a7fSStefano Zampini         ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
195716909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
195816909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
195916909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
1960b3338236SStefano Zampini           ierr = MatMult(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
196116909a7fSStefano Zampini         } else {
196216909a7fSStefano Zampini           ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1963b3338236SStefano Zampini           ierr = MatMult(lA,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
196416909a7fSStefano Zampini           ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
196516909a7fSStefano Zampini         }
196616909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
196716909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
196816909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
196916909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
197016909a7fSStefano Zampini       } else {
1971b097fa66SStefano Zampini         ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
197216909a7fSStefano Zampini       }
1973b097fa66SStefano Zampini     } else {
1974b097fa66SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1975b097fa66SStefano Zampini     }
19760c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
19770c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1978674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
1979b76ba322SStefano Zampini   } else {
19804fee134fSStefano Zampini     if (!pcbddc->benign_apply_coarse_only) {
1981674ae819SStefano Zampini       ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
1982b76ba322SStefano Zampini     }
19834fee134fSStefano Zampini   }
1984bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) {
19852c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!pcbddc->switch_static,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"You forgot to pass -pc_bddc_switch_static");
1986bc960bbfSJed Brown     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1987bc960bbfSJed Brown     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1988bc960bbfSJed Brown   }
1989b76ba322SStefano Zampini 
19902617d88aSStefano Zampini   /* Apply interface preconditioner
19912617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
1992dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
19932617d88aSStefano Zampini 
1994674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
1995674ae819SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
1996bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) {
1997bc960bbfSJed Brown     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1998bc960bbfSJed Brown     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec1_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1999bc960bbfSJed Brown     PetscFunctionReturn(0);
2000bc960bbfSJed Brown   }
20013b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
20020c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
20030c7d97c5SJed Brown   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2004b097fa66SStefano Zampini   if (n_B) {
200516909a7fSStefano Zampini     if (pcbddc->switch_static) {
200616909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
200716909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
200816909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
200916909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
201016909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
2011b3338236SStefano Zampini         ierr = MatMult(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
201216909a7fSStefano Zampini       } else {
201316909a7fSStefano Zampini         ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
2014b3338236SStefano Zampini         ierr = MatMult(lA,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
201516909a7fSStefano Zampini         ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
201616909a7fSStefano Zampini       }
201716909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
201816909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
201916909a7fSStefano Zampini     } else {
20200c7d97c5SJed Brown       ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
202116909a7fSStefano Zampini     }
202216909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
202316909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
2024b3338236SStefano Zampini       ierr = MatMult(lA,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
202516909a7fSStefano Zampini     } else {
202616909a7fSStefano Zampini       ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N);CHKERRQ(ierr);
2027b3338236SStefano Zampini       ierr = MatMult(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
202816909a7fSStefano Zampini       ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D);CHKERRQ(ierr);
202916909a7fSStefano Zampini     }
2030b097fa66SStefano Zampini   }
203155c176c0SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr);
2032df187020SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
203355c176c0SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr);
2034c0decd05SBarry Smith   ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec4_D);CHKERRQ(ierr);
2035efc2fbd9SStefano Zampini 
20368ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
2037b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2038b097fa66SStefano Zampini       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
2039b097fa66SStefano Zampini     } else {
2040b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
2041b097fa66SStefano Zampini     }
20420c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20430c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2044b097fa66SStefano Zampini   } else {
2045b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2046b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
2047b097fa66SStefano Zampini     } else {
2048b097fa66SStefano Zampini       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
2049b097fa66SStefano Zampini     }
2050b097fa66SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2051b097fa66SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2052b097fa66SStefano Zampini   }
205327b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
20541dd7afcfSStefano Zampini     if (pcbddc->benign_apply_coarse_only) {
2055580bdb30SBarry Smith       ierr = PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n);CHKERRQ(ierr);
20561dd7afcfSStefano Zampini     }
2057015636ebSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
2058efc2fbd9SStefano Zampini   }
20591f4df5f7SStefano Zampini 
20601dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2061f913dca9SStefano Zampini     pcbddc->work_change = r;
20621dd7afcfSStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
20631dd7afcfSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
20641dd7afcfSStefano Zampini   }
20650c7d97c5SJed Brown   PetscFunctionReturn(0);
20660c7d97c5SJed Brown }
206750efa1b5SStefano Zampini 
206850efa1b5SStefano Zampini /*
206950efa1b5SStefano Zampini    PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector.
207050efa1b5SStefano Zampini 
207150efa1b5SStefano Zampini    Input Parameters:
20720f202f7eSStefano Zampini +  pc - the preconditioner context
20730f202f7eSStefano Zampini -  r - input vector (global)
207450efa1b5SStefano Zampini 
207550efa1b5SStefano Zampini    Output Parameter:
207650efa1b5SStefano Zampini .  z - output vector (global)
207750efa1b5SStefano Zampini 
207850efa1b5SStefano Zampini    Application Interface Routine: PCApplyTranspose()
207950efa1b5SStefano Zampini  */
208050efa1b5SStefano Zampini PetscErrorCode PCApplyTranspose_BDDC(PC pc,Vec r,Vec z)
208150efa1b5SStefano Zampini {
208250efa1b5SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
208350efa1b5SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
2084b3338236SStefano Zampini   Mat               lA = NULL;
2085b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
208650efa1b5SStefano Zampini   PetscErrorCode    ierr;
208750efa1b5SStefano Zampini   const PetscScalar one = 1.0;
208850efa1b5SStefano Zampini   const PetscScalar m_one = -1.0;
208950efa1b5SStefano Zampini   const PetscScalar zero = 0.0;
209050efa1b5SStefano Zampini 
209150efa1b5SStefano Zampini   PetscFunctionBegin;
2092f3d41395Sstefano_zampini   ierr = PetscCitationsRegister(citation,&cited);CHKERRQ(ierr);
2093b3338236SStefano Zampini   if (pcbddc->switch_static) {
2094b3338236SStefano Zampini     ierr = MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat,&lA);CHKERRQ(ierr);
2095b3338236SStefano Zampini   }
20961dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
20971dd7afcfSStefano Zampini     Vec swap;
209827b6a85dSStefano Zampini 
209927b6a85dSStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
21001dd7afcfSStefano Zampini     swap = pcbddc->work_change;
21011dd7afcfSStefano Zampini     pcbddc->work_change = r;
21021dd7afcfSStefano Zampini     r = swap;
210327b6a85dSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
21048ae0ca82SStefano Zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->exact_dirichlet_trick_app && pcbddc->change_interior) {
210527b6a85dSStefano Zampini       ierr = VecCopy(r,pcis->vec1_global);CHKERRQ(ierr);
21068860a134SJunchao Zhang       ierr = VecLockReadPush(pcis->vec1_global);CHKERRQ(ierr);
21071dd7afcfSStefano Zampini     }
210827b6a85dSStefano Zampini   }
210927b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
2110537c1cdfSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
2111537c1cdfSStefano Zampini   }
21128ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
2113b097fa66SStefano Zampini     ierr = VecCopy(r,z);CHKERRQ(ierr);
211450efa1b5SStefano Zampini     /* First Dirichlet solve */
211550efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
211650efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
211750efa1b5SStefano Zampini     /*
211850efa1b5SStefano Zampini       Assembling right hand side for BDDC operator
2119b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
212050efa1b5SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
212150efa1b5SStefano Zampini     */
2122b097fa66SStefano Zampini     if (n_D) {
212355c176c0SStefano Zampini       ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr);
2124b097fa66SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
212555c176c0SStefano Zampini       ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr);
2126c0decd05SBarry Smith       ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D);CHKERRQ(ierr);
212750efa1b5SStefano Zampini       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
212816909a7fSStefano Zampini       if (pcbddc->switch_static) {
212916909a7fSStefano Zampini         ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
213016909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
213116909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
213216909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
2133b3338236SStefano Zampini           ierr = MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
213416909a7fSStefano Zampini         } else {
213516909a7fSStefano Zampini           ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
2136b3338236SStefano Zampini           ierr = MatMultTranspose(lA,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
213716909a7fSStefano Zampini           ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
213816909a7fSStefano Zampini         }
213916909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
214016909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
214116909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
214216909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
214316909a7fSStefano Zampini       } else {
2144b097fa66SStefano Zampini         ierr = MatMultTranspose(pcis->A_IB,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
214516909a7fSStefano Zampini       }
2146b097fa66SStefano Zampini     } else {
2147b097fa66SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
2148b097fa66SStefano Zampini     }
214950efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
215050efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
215150efa1b5SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
215250efa1b5SStefano Zampini   } else {
215350efa1b5SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
215450efa1b5SStefano Zampini   }
215550efa1b5SStefano Zampini 
215650efa1b5SStefano Zampini   /* Apply interface preconditioner
215750efa1b5SStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
2158dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_TRUE);CHKERRQ(ierr);
215950efa1b5SStefano Zampini 
216050efa1b5SStefano Zampini   /* Apply transpose of partition of unity operator */
216150efa1b5SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
216250efa1b5SStefano Zampini 
216350efa1b5SStefano Zampini   /* Second Dirichlet solve and assembling of output */
216450efa1b5SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
216550efa1b5SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2166b097fa66SStefano Zampini   if (n_B) {
216716909a7fSStefano Zampini     if (pcbddc->switch_static) {
216816909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
216916909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
217016909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
217116909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
217216909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
2173b3338236SStefano Zampini         ierr = MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
217416909a7fSStefano Zampini       } else {
217516909a7fSStefano Zampini         ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
2176b3338236SStefano Zampini         ierr = MatMultTranspose(lA,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
217716909a7fSStefano Zampini         ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
217816909a7fSStefano Zampini       }
217916909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
218016909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
218116909a7fSStefano Zampini     } else {
218250efa1b5SStefano Zampini       ierr = MatMultTranspose(pcis->A_BI,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
218316909a7fSStefano Zampini     }
218416909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
218516909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
2186b3338236SStefano Zampini       ierr = MatMultTranspose(lA,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
218716909a7fSStefano Zampini     } else {
218816909a7fSStefano Zampini       ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N);CHKERRQ(ierr);
2189b3338236SStefano Zampini       ierr = MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
219016909a7fSStefano Zampini       ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D);CHKERRQ(ierr);
219116909a7fSStefano Zampini     }
2192b097fa66SStefano Zampini   }
219355c176c0SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr);
2194b0147a47SStefano Zampini   ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
219555c176c0SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr);
2196c0decd05SBarry Smith   ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec4_D);CHKERRQ(ierr);
21978ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
2198b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2199b097fa66SStefano Zampini       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
2200b097fa66SStefano Zampini     } else {
2201b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
2202b097fa66SStefano Zampini     }
220350efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
220450efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2205b097fa66SStefano Zampini   } else {
2206b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2207b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
2208b097fa66SStefano Zampini     } else {
2209b097fa66SStefano Zampini       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
2210b097fa66SStefano Zampini     }
2211b097fa66SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2212b097fa66SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2213b097fa66SStefano Zampini   }
221427b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
2215537c1cdfSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
2216537c1cdfSStefano Zampini   }
22171dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2218f913dca9SStefano Zampini     pcbddc->work_change = r;
22191dd7afcfSStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
22201dd7afcfSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
22211dd7afcfSStefano Zampini   }
222250efa1b5SStefano Zampini   PetscFunctionReturn(0);
222350efa1b5SStefano Zampini }
2224674ae819SStefano Zampini 
22259326c5c6Sstefano_zampini PetscErrorCode PCReset_BDDC(PC pc)
2226da1bb401SStefano Zampini {
2227da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
22289326c5c6Sstefano_zampini   PC_IS          *pcis = (PC_IS*)pc->data;
22299326c5c6Sstefano_zampini   KSP            kspD,kspR,kspC;
2230da1bb401SStefano Zampini   PetscErrorCode ierr;
2231da1bb401SStefano Zampini 
2232da1bb401SStefano Zampini   PetscFunctionBegin;
2233674ae819SStefano Zampini   /* free BDDC custom data  */
2234674ae819SStefano Zampini   ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr);
2235674ae819SStefano Zampini   /* destroy objects related to topography */
2236674ae819SStefano Zampini   ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
223734a97f8cSStefano Zampini   /* destroy objects for scaling operator */
2238674ae819SStefano Zampini   ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
2239674ae819SStefano Zampini   /* free solvers stuff */
2240674ae819SStefano Zampini   ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
224162a6ff1dSStefano Zampini   /* free global vectors needed in presolve */
224262a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr);
224362a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr);
22441dd7afcfSStefano Zampini   /* free data created by PCIS */
22451dd7afcfSStefano Zampini   ierr = PCISDestroy(pc);CHKERRQ(ierr);
22469326c5c6Sstefano_zampini 
22479326c5c6Sstefano_zampini   /* restore defaults */
22489326c5c6Sstefano_zampini   kspD = pcbddc->ksp_D;
22499326c5c6Sstefano_zampini   kspR = pcbddc->ksp_R;
22509326c5c6Sstefano_zampini   kspC = pcbddc->coarse_ksp;
22519326c5c6Sstefano_zampini   ierr = PetscMemzero(pc->data,sizeof(*pcbddc));CHKERRQ(ierr);
22529326c5c6Sstefano_zampini   pcis->n_neigh                     = -1;
22539326c5c6Sstefano_zampini   pcis->scaling_factor              = 1.0;
22549326c5c6Sstefano_zampini   pcis->reusesubmatrices            = PETSC_TRUE;
22559326c5c6Sstefano_zampini   pcbddc->use_local_adj             = PETSC_TRUE;
22569326c5c6Sstefano_zampini   pcbddc->use_vertices              = PETSC_TRUE;
22579326c5c6Sstefano_zampini   pcbddc->use_edges                 = PETSC_TRUE;
22589326c5c6Sstefano_zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
22599326c5c6Sstefano_zampini   pcbddc->vertex_size               = 1;
22609326c5c6Sstefano_zampini   pcbddc->recompute_topography      = PETSC_TRUE;
22619326c5c6Sstefano_zampini   pcbddc->coarse_size               = -1;
22629326c5c6Sstefano_zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
22639326c5c6Sstefano_zampini   pcbddc->coarsening_ratio          = 8;
22649326c5c6Sstefano_zampini   pcbddc->coarse_eqs_per_proc       = 1;
22659326c5c6Sstefano_zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
22669326c5c6Sstefano_zampini   pcbddc->nedfield                  = -1;
22679326c5c6Sstefano_zampini   pcbddc->nedglobal                 = PETSC_TRUE;
22689326c5c6Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
22699326c5c6Sstefano_zampini   pcbddc->sub_schurs_layers         = -1;
22709326c5c6Sstefano_zampini   pcbddc->ksp_D                     = kspD;
22719326c5c6Sstefano_zampini   pcbddc->ksp_R                     = kspR;
22729326c5c6Sstefano_zampini   pcbddc->coarse_ksp                = kspC;
22739326c5c6Sstefano_zampini   PetscFunctionReturn(0);
22749326c5c6Sstefano_zampini }
22759326c5c6Sstefano_zampini 
22769326c5c6Sstefano_zampini PetscErrorCode PCDestroy_BDDC(PC pc)
22779326c5c6Sstefano_zampini {
22789326c5c6Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
22799326c5c6Sstefano_zampini   PetscErrorCode ierr;
22809326c5c6Sstefano_zampini 
22819326c5c6Sstefano_zampini   PetscFunctionBegin;
22829326c5c6Sstefano_zampini   ierr = PCReset_BDDC(pc);CHKERRQ(ierr);
22839326c5c6Sstefano_zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
22849326c5c6Sstefano_zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
22859326c5c6Sstefano_zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
2286a13144ffSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",NULL);CHKERRQ(ierr);
2287a198735bSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",NULL);CHKERRQ(ierr);
2288906d46d4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",NULL);CHKERRQ(ierr);
2289674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr);
229030368db7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",NULL);CHKERRQ(ierr);
2291bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr);
22922b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL);CHKERRQ(ierr);
2293b8ffe317SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL);CHKERRQ(ierr);
22942b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL);CHKERRQ(ierr);
2295bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
229682ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
2297bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
229882ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
2299bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
230082ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
2301bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
2302785d1243SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
2303bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr);
230463602bcaSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",NULL);CHKERRQ(ierr);
2305bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr);
2306bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr);
2307bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr);
2308bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr);
2309a06fd7f2SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",NULL);CHKERRQ(ierr);
2310ab8c8b98SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",NULL);CHKERRQ(ierr);
2311674ae819SStefano Zampini   ierr = PetscFree(pc->data);CHKERRQ(ierr);
2312da1bb401SStefano Zampini   PetscFunctionReturn(0);
2313da1bb401SStefano Zampini }
23141e6b0712SBarry Smith 
2315ab8c8b98SStefano Zampini static PetscErrorCode PCSetCoordinates_BDDC(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
2316ab8c8b98SStefano Zampini {
2317ab8c8b98SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2318ab8c8b98SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
2319ab8c8b98SStefano Zampini   PetscErrorCode ierr;
2320ab8c8b98SStefano Zampini 
2321ab8c8b98SStefano Zampini   PetscFunctionBegin;
2322ab8c8b98SStefano Zampini   ierr = PetscFree(mat_graph->coords);CHKERRQ(ierr);
2323ab8c8b98SStefano Zampini   ierr = PetscMalloc1(nloc*dim,&mat_graph->coords);CHKERRQ(ierr);
2324580bdb30SBarry Smith   ierr = PetscArraycpy(mat_graph->coords,coords,nloc*dim);CHKERRQ(ierr);
2325ab8c8b98SStefano Zampini   mat_graph->cnloc = nloc;
2326ab8c8b98SStefano Zampini   mat_graph->cdim  = dim;
2327ab8c8b98SStefano Zampini   mat_graph->cloc  = PETSC_FALSE;
23284f819b78SStefano Zampini   /* flg setup */
23294f819b78SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
23304f819b78SStefano Zampini   pcbddc->corner_selected = PETSC_FALSE;
2331ab8c8b98SStefano Zampini   PetscFunctionReturn(0);
2332ab8c8b98SStefano Zampini }
2333ab8c8b98SStefano Zampini 
2334a06fd7f2SStefano Zampini static PetscErrorCode PCPreSolveChangeRHS_BDDC(PC pc, PetscBool* change)
2335a06fd7f2SStefano Zampini {
2336a06fd7f2SStefano Zampini   PetscFunctionBegin;
2337a06fd7f2SStefano Zampini   *change = PETSC_TRUE;
2338a06fd7f2SStefano Zampini   PetscFunctionReturn(0);
2339a06fd7f2SStefano Zampini }
2340a06fd7f2SStefano Zampini 
23413425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
23423425bc38SStefano Zampini {
2343674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
2344266e20e9SStefano Zampini   Vec            work;
23453425bc38SStefano Zampini   PC_IS*         pcis;
23463425bc38SStefano Zampini   PC_BDDC*       pcbddc;
23473425bc38SStefano Zampini   PetscErrorCode ierr;
23480c7d97c5SJed Brown 
23493425bc38SStefano Zampini   PetscFunctionBegin;
23503425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
23513425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
23523425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
23533425bc38SStefano Zampini 
2354229984c5Sstefano_zampini   ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr);
2355229984c5Sstefano_zampini   /* copy rhs since we may change it during PCPreSolve_BDDC */
2356229984c5Sstefano_zampini   if (!pcbddc->original_rhs) {
2357229984c5Sstefano_zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
2358229984c5Sstefano_zampini   }
23596cc1294bSstefano_zampini   if (mat_ctx->rhs_flip) {
23606cc1294bSstefano_zampini     ierr = VecPointwiseMult(pcbddc->original_rhs,standard_rhs,mat_ctx->rhs_flip);CHKERRQ(ierr);
23616cc1294bSstefano_zampini   } else {
2362229984c5Sstefano_zampini     ierr = VecCopy(standard_rhs,pcbddc->original_rhs);CHKERRQ(ierr);
23636cc1294bSstefano_zampini   }
2364af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
2365229984c5Sstefano_zampini     /* interface pressure rhs */
2366022d8d2bSstefano_zampini     ierr = VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2367022d8d2bSstefano_zampini     ierr = VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2368229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2369229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
23706cc1294bSstefano_zampini     if (!mat_ctx->rhs_flip) {
2371229984c5Sstefano_zampini       ierr = VecScale(fetidp_flux_rhs,-1.);CHKERRQ(ierr);
2372229984c5Sstefano_zampini     }
23736cc1294bSstefano_zampini   }
2374c08af4c6SStefano Zampini   /*
2375c08af4c6SStefano Zampini      change of basis for physical rhs if needed
2376c08af4c6SStefano Zampini      It also changes the rhs in case of dirichlet boundaries
2377c08af4c6SStefano Zampini   */
23783738a8e6SStefano Zampini   ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,pcbddc->original_rhs,NULL);CHKERRQ(ierr);
2379fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
23803738a8e6SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcbddc->original_rhs,pcbddc->work_change);CHKERRQ(ierr);
23813738a8e6SStefano Zampini     work = pcbddc->work_change;
2382fc17d649SStefano Zampini    } else {
23833738a8e6SStefano Zampini     work = pcbddc->original_rhs;
2384fc17d649SStefano Zampini   }
23853425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
2386266e20e9SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2387266e20e9SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2388fb223d50SStefano Zampini   /* scale rhs since it should be unassembled */
2389fb223d50SStefano Zampini   /* TODO use counter scaling? (also below) */
2390266e20e9SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2391266e20e9SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2392674ae819SStefano Zampini   /* Apply partition of unity */
23933425bc38SStefano Zampini   ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
2394266e20e9SStefano Zampini   /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
23958eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
23963425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
239755c176c0SStefano Zampini     ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0);CHKERRQ(ierr);
23983425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
239955c176c0SStefano Zampini     ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0);CHKERRQ(ierr);
2400c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
24013425bc38SStefano Zampini     ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr);
24023425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr);
2403266e20e9SStefano Zampini     ierr = VecSet(work,0.0);CHKERRQ(ierr);
2404266e20e9SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2405266e20e9SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2406266e20e9SStefano Zampini     /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
2407266e20e9SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2408266e20e9SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
24093425bc38SStefano Zampini     ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
24103425bc38SStefano Zampini   }
24113425bc38SStefano Zampini   /* BDDC rhs */
24123425bc38SStefano Zampini   ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr);
24138eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
24143425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
24153425bc38SStefano Zampini   }
24163425bc38SStefano Zampini   /* apply BDDC */
2417580bdb30SBarry Smith   ierr = PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n);CHKERRQ(ierr);
2418dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
2419580bdb30SBarry Smith   ierr = PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n);CHKERRQ(ierr);
2420229984c5Sstefano_zampini 
24213425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
24223425bc38SStefano Zampini   ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr);
24233425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
24243425bc38SStefano Zampini   ierr = VecScatterEnd(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2425229984c5Sstefano_zampini   /* Add contribution to interface pressures */
2426229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
2427229984c5Sstefano_zampini     ierr = MatMult(mat_ctx->B_BB,pcis->vec1_B,mat_ctx->vP);CHKERRQ(ierr);
2428229984c5Sstefano_zampini     if (pcbddc->switch_static) {
2429229984c5Sstefano_zampini       ierr = MatMultAdd(mat_ctx->B_BI,pcis->vec1_D,mat_ctx->vP,mat_ctx->vP);CHKERRQ(ierr);
2430229984c5Sstefano_zampini     }
2431229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2432229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2433229984c5Sstefano_zampini   }
24343425bc38SStefano Zampini   PetscFunctionReturn(0);
24353425bc38SStefano Zampini }
24361e6b0712SBarry Smith 
24373425bc38SStefano Zampini /*@
24380f202f7eSStefano Zampini  PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side
24393425bc38SStefano Zampini 
24403425bc38SStefano Zampini    Collective
24413425bc38SStefano Zampini 
24423425bc38SStefano Zampini    Input Parameters:
24430f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix object obtained by a call to PCBDDCCreateFETIDPOperators
24440f202f7eSStefano Zampini -  standard_rhs    - the right-hand side of the original linear system
24453425bc38SStefano Zampini 
24463425bc38SStefano Zampini    Output Parameters:
24470f202f7eSStefano Zampini .  fetidp_flux_rhs - the right-hand side for the FETI-DP linear system
24483425bc38SStefano Zampini 
24493425bc38SStefano Zampini    Level: developer
24503425bc38SStefano Zampini 
24513425bc38SStefano Zampini    Notes:
24523425bc38SStefano Zampini 
24530f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetSolution
24543425bc38SStefano Zampini @*/
24553425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
24563425bc38SStefano Zampini {
2457674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
24583425bc38SStefano Zampini   PetscErrorCode ierr;
24593425bc38SStefano Zampini 
24603425bc38SStefano Zampini   PetscFunctionBegin;
2461266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1);
2462266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_rhs,VEC_CLASSID,2);
2463266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_rhs,VEC_CLASSID,3);
24643425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
2465163d334eSBarry Smith   ierr = PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr);
24663425bc38SStefano Zampini   PetscFunctionReturn(0);
24673425bc38SStefano Zampini }
24681e6b0712SBarry Smith 
24693425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
24703425bc38SStefano Zampini {
2471674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
24723425bc38SStefano Zampini   PC_IS*         pcis;
24733425bc38SStefano Zampini   PC_BDDC*       pcbddc;
24743425bc38SStefano Zampini   PetscErrorCode ierr;
2475229984c5Sstefano_zampini   Vec            work;
24763425bc38SStefano Zampini 
24773425bc38SStefano Zampini   PetscFunctionBegin;
24783425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
24793425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
24803425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
24813425bc38SStefano Zampini 
24823425bc38SStefano Zampini   /* apply B_delta^T */
2483af140850Sstefano_zampini   ierr = VecSet(pcis->vec1_B,0.);CHKERRQ(ierr);
24843425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
24853425bc38SStefano Zampini   ierr = VecScatterEnd(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
24863425bc38SStefano Zampini   ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
2487229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
2488229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2489229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2490229984c5Sstefano_zampini     ierr = MatMultAdd(mat_ctx->Bt_BB,mat_ctx->vP,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
2491229984c5Sstefano_zampini   }
2492229984c5Sstefano_zampini 
24933425bc38SStefano Zampini   /* compute rhs for BDDC application */
24943425bc38SStefano Zampini   ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr);
24958eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
24963425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
2497229984c5Sstefano_zampini     if (mat_ctx->l2g_p) {
2498229984c5Sstefano_zampini       ierr = VecScale(mat_ctx->vP,-1.);CHKERRQ(ierr);
2499229984c5Sstefano_zampini       ierr = MatMultAdd(mat_ctx->Bt_BI,mat_ctx->vP,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr);
25003425bc38SStefano Zampini     }
2501229984c5Sstefano_zampini   }
2502229984c5Sstefano_zampini 
25033425bc38SStefano Zampini   /* apply BDDC */
2504580bdb30SBarry Smith   ierr = PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n);CHKERRQ(ierr);
2505dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
2506229984c5Sstefano_zampini 
2507229984c5Sstefano_zampini   /* put values into global vector */
2508af140850Sstefano_zampini   if (pcbddc->ChangeOfBasisMatrix) work = pcbddc->work_change;
2509af140850Sstefano_zampini   else work = standard_sol;
2510229984c5Sstefano_zampini   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2511229984c5Sstefano_zampini   ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
25128eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
25133425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
25143425bc38SStefano Zampini     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr);
251500f6b531SStefano Zampini     ierr = VecAYPX(pcis->vec1_D,-1.0,mat_ctx->temp_solution_D);CHKERRQ(ierr);
251655c176c0SStefano Zampini     ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0);CHKERRQ(ierr);
251700f6b531SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr);
251855c176c0SStefano Zampini     ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0);CHKERRQ(ierr);
2519c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
25203425bc38SStefano Zampini   }
2521229984c5Sstefano_zampini 
2522229984c5Sstefano_zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2523229984c5Sstefano_zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2524266e20e9SStefano Zampini   /* add p0 solution to final solution */
2525229984c5Sstefano_zampini   ierr = PCBDDCBenignGetOrSetP0(mat_ctx->pc,work,PETSC_FALSE);CHKERRQ(ierr);
2526fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2527af140850Sstefano_zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,work,standard_sol);CHKERRQ(ierr);
2528fc17d649SStefano Zampini   }
2529af140850Sstefano_zampini   ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr);
2530af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
2531229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2532229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2533229984c5Sstefano_zampini   }
25343425bc38SStefano Zampini   PetscFunctionReturn(0);
25353425bc38SStefano Zampini }
25361e6b0712SBarry Smith 
25375a1e936bSStefano Zampini static PetscErrorCode PCView_BDDCIPC(PC pc, PetscViewer viewer)
25385a1e936bSStefano Zampini {
25395a1e936bSStefano Zampini   PetscErrorCode ierr;
25405a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25415a1e936bSStefano Zampini   PetscBool      isascii;
25425a1e936bSStefano Zampini 
25435a1e936bSStefano Zampini   PetscFunctionBegin;
25443ec1f749SStefano Zampini   ierr = PCShellGetContext(pc,&bddcipc_ctx);CHKERRQ(ierr);
25455a1e936bSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
25465a1e936bSStefano Zampini   if (isascii) {
25475a1e936bSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"BDDC interface preconditioner\n");CHKERRQ(ierr);
25485a1e936bSStefano Zampini   }
25495a1e936bSStefano Zampini   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
25505a1e936bSStefano Zampini   ierr = PCView(bddcipc_ctx->bddc,viewer);CHKERRQ(ierr);
25515a1e936bSStefano Zampini   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
25525a1e936bSStefano Zampini   PetscFunctionReturn(0);
25535a1e936bSStefano Zampini }
25545a1e936bSStefano Zampini 
25555a1e936bSStefano Zampini static PetscErrorCode PCSetUp_BDDCIPC(PC pc)
25565a1e936bSStefano Zampini {
25575a1e936bSStefano Zampini   PetscErrorCode ierr;
25585a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25595a1e936bSStefano Zampini   PetscBool      isbddc;
25605a1e936bSStefano Zampini   Vec            vv;
25615a1e936bSStefano Zampini   IS             is;
25625a1e936bSStefano Zampini   PC_IS          *pcis;
25635a1e936bSStefano Zampini 
25645a1e936bSStefano Zampini   PetscFunctionBegin;
25653ec1f749SStefano Zampini   ierr = PCShellGetContext(pc,&bddcipc_ctx);CHKERRQ(ierr);
25665a1e936bSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)bddcipc_ctx->bddc,PCBDDC,&isbddc);CHKERRQ(ierr);
25672c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!isbddc,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid type %s. Must be of type bddc",((PetscObject)bddcipc_ctx->bddc)->type_name);
25685a1e936bSStefano Zampini   ierr = PCSetUp(bddcipc_ctx->bddc);CHKERRQ(ierr);
25695a1e936bSStefano Zampini 
25705a1e936bSStefano Zampini   /* create interface scatter */
25715a1e936bSStefano Zampini   pcis = (PC_IS*)(bddcipc_ctx->bddc->data);
25725a1e936bSStefano Zampini   ierr = VecScatterDestroy(&bddcipc_ctx->g2l);CHKERRQ(ierr);
25735a1e936bSStefano Zampini   ierr = MatCreateVecs(pc->pmat,&vv,NULL);CHKERRQ(ierr);
25745a1e936bSStefano Zampini   ierr = ISRenumber(pcis->is_B_global,NULL,NULL,&is);CHKERRQ(ierr);
25759448b7f1SJunchao Zhang   ierr = VecScatterCreate(vv,is,pcis->vec1_B,NULL,&bddcipc_ctx->g2l);CHKERRQ(ierr);
25765a1e936bSStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
25775a1e936bSStefano Zampini   ierr = VecDestroy(&vv);CHKERRQ(ierr);
25785a1e936bSStefano Zampini   PetscFunctionReturn(0);
25795a1e936bSStefano Zampini }
25805a1e936bSStefano Zampini 
25815a1e936bSStefano Zampini static PetscErrorCode PCApply_BDDCIPC(PC pc, Vec r, Vec x)
25825a1e936bSStefano Zampini {
25835a1e936bSStefano Zampini   PetscErrorCode ierr;
25845a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25855a1e936bSStefano Zampini   PC_IS          *pcis;
25865a1e936bSStefano Zampini   VecScatter     tmps;
25875a1e936bSStefano Zampini 
25885a1e936bSStefano Zampini   PetscFunctionBegin;
25893ec1f749SStefano Zampini   ierr = PCShellGetContext(pc,&bddcipc_ctx);CHKERRQ(ierr);
25905a1e936bSStefano Zampini   pcis = (PC_IS*)(bddcipc_ctx->bddc->data);
25915a1e936bSStefano Zampini   tmps = pcis->global_to_B;
25925a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
25935a1e936bSStefano Zampini   ierr = PCBDDCScalingRestriction(bddcipc_ctx->bddc,r,pcis->vec1_B);CHKERRQ(ierr);
25945a1e936bSStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc,PETSC_FALSE);CHKERRQ(ierr);
25955a1e936bSStefano Zampini   ierr = PCBDDCScalingExtension(bddcipc_ctx->bddc,pcis->vec1_B,x);CHKERRQ(ierr);
25965a1e936bSStefano Zampini   pcis->global_to_B = tmps;
25975a1e936bSStefano Zampini   PetscFunctionReturn(0);
25985a1e936bSStefano Zampini }
25995a1e936bSStefano Zampini 
26005a1e936bSStefano Zampini static PetscErrorCode PCApplyTranspose_BDDCIPC(PC pc, Vec r, Vec x)
26015a1e936bSStefano Zampini {
26025a1e936bSStefano Zampini   PetscErrorCode ierr;
26035a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
26045a1e936bSStefano Zampini   PC_IS          *pcis;
26055a1e936bSStefano Zampini   VecScatter     tmps;
26065a1e936bSStefano Zampini 
26075a1e936bSStefano Zampini   PetscFunctionBegin;
26083ec1f749SStefano Zampini   ierr = PCShellGetContext(pc,&bddcipc_ctx);CHKERRQ(ierr);
26095a1e936bSStefano Zampini   pcis = (PC_IS*)(bddcipc_ctx->bddc->data);
26105a1e936bSStefano Zampini   tmps = pcis->global_to_B;
26115a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
26125a1e936bSStefano Zampini   ierr = PCBDDCScalingRestriction(bddcipc_ctx->bddc,r,pcis->vec1_B);CHKERRQ(ierr);
26135a1e936bSStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc,PETSC_TRUE);CHKERRQ(ierr);
26145a1e936bSStefano Zampini   ierr = PCBDDCScalingExtension(bddcipc_ctx->bddc,pcis->vec1_B,x);CHKERRQ(ierr);
26155a1e936bSStefano Zampini   pcis->global_to_B = tmps;
26165a1e936bSStefano Zampini   PetscFunctionReturn(0);
26175a1e936bSStefano Zampini }
26185a1e936bSStefano Zampini 
26195a1e936bSStefano Zampini static PetscErrorCode PCDestroy_BDDCIPC(PC pc)
26205a1e936bSStefano Zampini {
26215a1e936bSStefano Zampini   PetscErrorCode ierr;
26225a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
26235a1e936bSStefano Zampini 
26245a1e936bSStefano Zampini   PetscFunctionBegin;
26253ec1f749SStefano Zampini   ierr = PCShellGetContext(pc,&bddcipc_ctx);CHKERRQ(ierr);
26265a1e936bSStefano Zampini   ierr = PCDestroy(&bddcipc_ctx->bddc);CHKERRQ(ierr);
26275a1e936bSStefano Zampini   ierr = VecScatterDestroy(&bddcipc_ctx->g2l);CHKERRQ(ierr);
26285a1e936bSStefano Zampini   ierr = PetscFree(bddcipc_ctx);CHKERRQ(ierr);
26295a1e936bSStefano Zampini   PetscFunctionReturn(0);
26305a1e936bSStefano Zampini }
26315a1e936bSStefano Zampini 
26323425bc38SStefano Zampini /*@
26330f202f7eSStefano Zampini  PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system
26343425bc38SStefano Zampini 
26353425bc38SStefano Zampini    Collective
26363425bc38SStefano Zampini 
26373425bc38SStefano Zampini    Input Parameters:
26380f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators
26390f202f7eSStefano Zampini -  fetidp_flux_sol - the solution of the FETI-DP linear system
26403425bc38SStefano Zampini 
26413425bc38SStefano Zampini    Output Parameters:
26420f202f7eSStefano Zampini .  standard_sol    - the solution defined on the physical domain
26433425bc38SStefano Zampini 
26443425bc38SStefano Zampini    Level: developer
26453425bc38SStefano Zampini 
26463425bc38SStefano Zampini    Notes:
26473425bc38SStefano Zampini 
26480f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetRHS
26493425bc38SStefano Zampini @*/
26503425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
26513425bc38SStefano Zampini {
2652674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
26533425bc38SStefano Zampini   PetscErrorCode ierr;
26543425bc38SStefano Zampini 
26553425bc38SStefano Zampini   PetscFunctionBegin;
2656266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1);
2657266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_sol,VEC_CLASSID,2);
2658266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_sol,VEC_CLASSID,3);
26593425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
2660163d334eSBarry Smith   ierr = PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr);
26613425bc38SStefano Zampini   PetscFunctionReturn(0);
26623425bc38SStefano Zampini }
26631e6b0712SBarry Smith 
2664547c9a8eSstefano_zampini static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, PetscBool fully_redundant, const char* prefix, Mat *fetidp_mat, PC *fetidp_pc)
26653425bc38SStefano Zampini {
2666674ae819SStefano Zampini 
2667674ae819SStefano Zampini   FETIDPMat_ctx  fetidpmat_ctx;
26683425bc38SStefano Zampini   Mat            newmat;
2669674ae819SStefano Zampini   FETIDPPC_ctx   fetidppc_ctx;
26703425bc38SStefano Zampini   PC             newpc;
2671ce94432eSBarry Smith   MPI_Comm       comm;
26723425bc38SStefano Zampini   PetscErrorCode ierr;
26733425bc38SStefano Zampini 
26743425bc38SStefano Zampini   PetscFunctionBegin;
2675ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
267615579a77SStefano Zampini   /* FETI-DP matrix */
26773425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr);
26781720468bSStefano Zampini   fetidpmat_ctx->fully_redundant = fully_redundant;
26793425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr);
2680a5bb87b3Sstefano_zampini   ierr = MatCreateShell(comm,fetidpmat_ctx->n,fetidpmat_ctx->n,fetidpmat_ctx->N,fetidpmat_ctx->N,fetidpmat_ctx,&newmat);CHKERRQ(ierr);
268115579a77SStefano Zampini   ierr = PetscObjectSetName((PetscObject)newmat,!fetidpmat_ctx->l2g_lambda_only ? "F" : "G");CHKERRQ(ierr);
26823425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr);
2683edf7251bSStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT_TRANSPOSE,(void (*)(void))FETIDPMatMultTranspose);CHKERRQ(ierr);
26843425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr);
268515579a77SStefano Zampini   /* propagate MatOptions */
268615579a77SStefano Zampini   {
268715579a77SStefano Zampini     PC_BDDC   *pcbddc = (PC_BDDC*)fetidpmat_ctx->pc->data;
268815579a77SStefano Zampini     PetscBool issym;
268915579a77SStefano Zampini 
269015579a77SStefano Zampini     ierr = MatGetOption(pc->mat,MAT_SYMMETRIC,&issym);CHKERRQ(ierr);
269115579a77SStefano Zampini     if (issym || pcbddc->symmetric_primal) {
269215579a77SStefano Zampini       ierr = MatSetOption(newmat,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
269315579a77SStefano Zampini     }
269415579a77SStefano Zampini   }
2695547c9a8eSstefano_zampini   ierr = MatSetOptionsPrefix(newmat,prefix);CHKERRQ(ierr);
2696547c9a8eSstefano_zampini   ierr = MatAppendOptionsPrefix(newmat,"fetidp_");CHKERRQ(ierr);
26973425bc38SStefano Zampini   ierr = MatSetUp(newmat);CHKERRQ(ierr);
269815579a77SStefano Zampini   /* FETI-DP preconditioner */
26993425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr);
27003425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr);
27013425bc38SStefano Zampini   ierr = PCCreate(comm,&newpc);CHKERRQ(ierr);
2702e1214c54Sstefano_zampini   ierr = PCSetOperators(newpc,newmat,newmat);CHKERRQ(ierr);
2703e1214c54Sstefano_zampini   ierr = PCSetOptionsPrefix(newpc,prefix);CHKERRQ(ierr);
2704e1214c54Sstefano_zampini   ierr = PCAppendOptionsPrefix(newpc,"fetidp_");CHKERRQ(ierr);
2705399ffe99SStefano Zampini   ierr = PCSetErrorIfFailure(newpc,pc->erroriffailure);CHKERRQ(ierr);
270615579a77SStefano Zampini   if (!fetidpmat_ctx->l2g_lambda_only) { /* standard FETI-DP */
27073425bc38SStefano Zampini     ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
270815579a77SStefano Zampini     ierr = PCShellSetName(newpc,"FETI-DP multipliers");CHKERRQ(ierr);
27093425bc38SStefano Zampini     ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr);
27103425bc38SStefano Zampini     ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr);
2711edf7251bSStefano Zampini     ierr = PCShellSetApplyTranspose(newpc,FETIDPPCApplyTranspose);CHKERRQ(ierr);
2712c45b8d2dSstefano_zampini     ierr = PCShellSetView(newpc,FETIDPPCView);CHKERRQ(ierr);
27133425bc38SStefano Zampini     ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
27145a1e936bSStefano Zampini   } else { /* saddle-point FETI-DP */
27155a1e936bSStefano Zampini     Mat       M;
27165a1e936bSStefano Zampini     PetscInt  psize;
27175a1e936bSStefano Zampini     PetscBool fake = PETSC_FALSE, isfieldsplit;
2718e1214c54Sstefano_zampini 
271915579a77SStefano Zampini     ierr = ISViewFromOptions(fetidpmat_ctx->lagrange,NULL,"-lag_view");CHKERRQ(ierr);
272015579a77SStefano Zampini     ierr = ISViewFromOptions(fetidpmat_ctx->pressure,NULL,"-press_view");CHKERRQ(ierr);
2721e1214c54Sstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_PPmat",(PetscObject*)&M);CHKERRQ(ierr);
2722e1214c54Sstefano_zampini     ierr = PCSetType(newpc,PCFIELDSPLIT);CHKERRQ(ierr);
2723e1214c54Sstefano_zampini     ierr = PCFieldSplitSetIS(newpc,"lag",fetidpmat_ctx->lagrange);CHKERRQ(ierr);
2724e1214c54Sstefano_zampini     ierr = PCFieldSplitSetIS(newpc,"p",fetidpmat_ctx->pressure);CHKERRQ(ierr);
2725e1214c54Sstefano_zampini     ierr = PCFieldSplitSetType(newpc,PC_COMPOSITE_SCHUR);CHKERRQ(ierr);
272640c75d76SStefano Zampini     ierr = PCFieldSplitSetSchurFactType(newpc,PC_FIELDSPLIT_SCHUR_FACT_DIAG);CHKERRQ(ierr);
27275a1e936bSStefano Zampini     ierr = ISGetSize(fetidpmat_ctx->pressure,&psize);CHKERRQ(ierr);
27285a1e936bSStefano Zampini     if (psize != M->rmap->N) {
27295a1e936bSStefano Zampini       Mat      M2;
27305a1e936bSStefano Zampini       PetscInt lpsize;
27315a1e936bSStefano Zampini 
27325a1e936bSStefano Zampini       fake = PETSC_TRUE;
27335a1e936bSStefano Zampini       ierr = ISGetLocalSize(fetidpmat_ctx->pressure,&lpsize);CHKERRQ(ierr);
27345a1e936bSStefano Zampini       ierr = MatCreate(comm,&M2);CHKERRQ(ierr);
27355a1e936bSStefano Zampini       ierr = MatSetType(M2,MATAIJ);CHKERRQ(ierr);
27365a1e936bSStefano Zampini       ierr = MatSetSizes(M2,lpsize,lpsize,psize,psize);CHKERRQ(ierr);
27375a1e936bSStefano Zampini       ierr = MatSetUp(M2);CHKERRQ(ierr);
27385a1e936bSStefano Zampini       ierr = MatAssemblyBegin(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27395a1e936bSStefano Zampini       ierr = MatAssemblyEnd(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27405a1e936bSStefano Zampini       ierr = PCFieldSplitSetSchurPre(newpc,PC_FIELDSPLIT_SCHUR_PRE_USER,M2);CHKERRQ(ierr);
27415a1e936bSStefano Zampini       ierr = MatDestroy(&M2);CHKERRQ(ierr);
27425a1e936bSStefano Zampini     } else {
2743e1214c54Sstefano_zampini       ierr = PCFieldSplitSetSchurPre(newpc,PC_FIELDSPLIT_SCHUR_PRE_USER,M);CHKERRQ(ierr);
27445a1e936bSStefano Zampini     }
2745c096484dSStefano Zampini     ierr = PCFieldSplitSetSchurScale(newpc,1.0);CHKERRQ(ierr);
274615579a77SStefano Zampini 
274715579a77SStefano Zampini     /* we need to setfromoptions and setup here to access the blocks */
2748e1214c54Sstefano_zampini     ierr = PCSetFromOptions(newpc);CHKERRQ(ierr);
2749e1214c54Sstefano_zampini     ierr = PCSetUp(newpc);CHKERRQ(ierr);
2750e1214c54Sstefano_zampini 
27515a1e936bSStefano Zampini     /* user may have changed the type (e.g. -fetidp_pc_type none) */
27525a1e936bSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)newpc,PCFIELDSPLIT,&isfieldsplit);CHKERRQ(ierr);
27535a1e936bSStefano Zampini     if (isfieldsplit) {
27545a1e936bSStefano Zampini       KSP       *ksps;
27555a1e936bSStefano Zampini       PC        ppc,lagpc;
27565a1e936bSStefano Zampini       PetscInt  nn;
2757064a4176SStefano Zampini       PetscBool ismatis,matisok = PETSC_FALSE,check = PETSC_FALSE;
27585a1e936bSStefano Zampini 
2759e1214c54Sstefano_zampini       /* set the solver for the (0,0) block */
27605a1e936bSStefano Zampini       ierr = PCFieldSplitSchurGetSubKSP(newpc,&nn,&ksps);CHKERRQ(ierr);
27615a1e936bSStefano Zampini       if (!nn) { /* not of type PC_COMPOSITE_SCHUR */
276240c75d76SStefano Zampini         ierr = PCFieldSplitGetSubKSP(newpc,&nn,&ksps);CHKERRQ(ierr);
27635a1e936bSStefano Zampini         if (!fake) { /* pass pmat to the pressure solver */
27645a1e936bSStefano Zampini           Mat F;
27655a1e936bSStefano Zampini 
27665a1e936bSStefano Zampini           ierr = KSPGetOperators(ksps[1],&F,NULL);CHKERRQ(ierr);
27675a1e936bSStefano Zampini           ierr = KSPSetOperators(ksps[1],F,M);CHKERRQ(ierr);
27685a1e936bSStefano Zampini         }
27695a1e936bSStefano Zampini       } else {
27705a1e936bSStefano Zampini         PetscBool issym;
27715a1e936bSStefano Zampini         Mat       S;
27725a1e936bSStefano Zampini 
27735a1e936bSStefano Zampini         ierr = PCFieldSplitSchurGetS(newpc,&S);CHKERRQ(ierr);
27745a1e936bSStefano Zampini 
27755a1e936bSStefano Zampini         ierr = MatGetOption(newmat,MAT_SYMMETRIC,&issym);CHKERRQ(ierr);
27765a1e936bSStefano Zampini         if (issym) {
27775a1e936bSStefano Zampini           ierr = MatSetOption(S,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
27785a1e936bSStefano Zampini         }
27795a1e936bSStefano Zampini       }
27805a1e936bSStefano Zampini       ierr = KSPGetPC(ksps[0],&lagpc);CHKERRQ(ierr);
2781e1214c54Sstefano_zampini       ierr = PCSetType(lagpc,PCSHELL);CHKERRQ(ierr);
27825a1e936bSStefano Zampini       ierr = PCShellSetName(lagpc,"FETI-DP multipliers");CHKERRQ(ierr);
2783e1214c54Sstefano_zampini       ierr = PCShellSetContext(lagpc,fetidppc_ctx);CHKERRQ(ierr);
2784e1214c54Sstefano_zampini       ierr = PCShellSetApply(lagpc,FETIDPPCApply);CHKERRQ(ierr);
2785e1214c54Sstefano_zampini       ierr = PCShellSetApplyTranspose(lagpc,FETIDPPCApplyTranspose);CHKERRQ(ierr);
2786e1214c54Sstefano_zampini       ierr = PCShellSetView(lagpc,FETIDPPCView);CHKERRQ(ierr);
2787e1214c54Sstefano_zampini       ierr = PCShellSetDestroy(lagpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
27885a1e936bSStefano Zampini 
27895a1e936bSStefano Zampini       /* Olof's idea: interface Schur complement preconditioner for the mass matrix */
27905a1e936bSStefano Zampini       ierr = KSPGetPC(ksps[1],&ppc);CHKERRQ(ierr);
27915a1e936bSStefano Zampini       if (fake) {
27925a1e936bSStefano Zampini         BDDCIPC_ctx    bddcipc_ctx;
2793ff11fd76SStefano Zampini         PetscContainer c;
27945a1e936bSStefano Zampini 
27955a1e936bSStefano Zampini         matisok = PETSC_TRUE;
27965a1e936bSStefano Zampini 
27975a1e936bSStefano Zampini         /* create inner BDDC solver */
27985a1e936bSStefano Zampini         ierr = PetscNew(&bddcipc_ctx);CHKERRQ(ierr);
27995a1e936bSStefano Zampini         ierr = PCCreate(comm,&bddcipc_ctx->bddc);CHKERRQ(ierr);
28005a1e936bSStefano Zampini         ierr = PCSetType(bddcipc_ctx->bddc,PCBDDC);CHKERRQ(ierr);
28015a1e936bSStefano Zampini         ierr = PCSetOperators(bddcipc_ctx->bddc,M,M);CHKERRQ(ierr);
2802ff11fd76SStefano Zampini         ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_pCSR",(PetscObject*)&c);CHKERRQ(ierr);
2803ff11fd76SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)M,MATIS,&ismatis);CHKERRQ(ierr);
2804ff11fd76SStefano Zampini         if (c && ismatis) {
2805ff11fd76SStefano Zampini           Mat      lM;
2806ff11fd76SStefano Zampini           PetscInt *csr,n;
2807ff11fd76SStefano Zampini 
2808ff11fd76SStefano Zampini           ierr = MatISGetLocalMat(M,&lM);CHKERRQ(ierr);
2809ff11fd76SStefano Zampini           ierr = MatGetSize(lM,&n,NULL);CHKERRQ(ierr);
2810ff11fd76SStefano Zampini           ierr = PetscContainerGetPointer(c,(void**)&csr);CHKERRQ(ierr);
2811ff11fd76SStefano Zampini           ierr = PCBDDCSetLocalAdjacencyGraph(bddcipc_ctx->bddc,n,csr,csr + (n + 1),PETSC_COPY_VALUES);CHKERRQ(ierr);
2812ff11fd76SStefano Zampini           ierr = MatISRestoreLocalMat(M,&lM);CHKERRQ(ierr);
2813ff11fd76SStefano Zampini         }
28145a1e936bSStefano Zampini         ierr = PCSetOptionsPrefix(bddcipc_ctx->bddc,((PetscObject)ksps[1])->prefix);CHKERRQ(ierr);
28155a1e936bSStefano Zampini         ierr = PCSetErrorIfFailure(bddcipc_ctx->bddc,pc->erroriffailure);CHKERRQ(ierr);
28165a1e936bSStefano Zampini         ierr = PCSetFromOptions(bddcipc_ctx->bddc);CHKERRQ(ierr);
28175a1e936bSStefano Zampini 
28185a1e936bSStefano Zampini         /* wrap the interface application */
28195a1e936bSStefano Zampini         ierr = PCSetType(ppc,PCSHELL);CHKERRQ(ierr);
28205a1e936bSStefano Zampini         ierr = PCShellSetName(ppc,"FETI-DP pressure");CHKERRQ(ierr);
28215a1e936bSStefano Zampini         ierr = PCShellSetContext(ppc,bddcipc_ctx);CHKERRQ(ierr);
28225a1e936bSStefano Zampini         ierr = PCShellSetSetUp(ppc,PCSetUp_BDDCIPC);CHKERRQ(ierr);
28235a1e936bSStefano Zampini         ierr = PCShellSetApply(ppc,PCApply_BDDCIPC);CHKERRQ(ierr);
28245a1e936bSStefano Zampini         ierr = PCShellSetApplyTranspose(ppc,PCApplyTranspose_BDDCIPC);CHKERRQ(ierr);
28255a1e936bSStefano Zampini         ierr = PCShellSetView(ppc,PCView_BDDCIPC);CHKERRQ(ierr);
28265a1e936bSStefano Zampini         ierr = PCShellSetDestroy(ppc,PCDestroy_BDDCIPC);CHKERRQ(ierr);
28275a1e936bSStefano Zampini       }
28285a1e936bSStefano Zampini 
28295a1e936bSStefano Zampini       /* determine if we need to assemble M to construct a preconditioner */
28305a1e936bSStefano Zampini       if (!matisok) {
28315a1e936bSStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)M,MATIS,&ismatis);CHKERRQ(ierr);
28325a1e936bSStefano Zampini         ierr = PetscObjectTypeCompareAny((PetscObject)ppc,&matisok,PCBDDC,PCJACOBI,PCNONE,PCMG,"");CHKERRQ(ierr);
28335a1e936bSStefano Zampini         if (ismatis && !matisok) {
28345a1e936bSStefano Zampini           ierr = MatConvert(M,MATAIJ,MAT_INPLACE_MATRIX,&M);CHKERRQ(ierr);
28355a1e936bSStefano Zampini         }
28365a1e936bSStefano Zampini       }
2837064a4176SStefano Zampini 
2838064a4176SStefano Zampini       /* run the subproblems to check convergence */
2839064a4176SStefano Zampini       ierr = PetscOptionsGetBool(NULL,((PetscObject)newmat)->prefix,"-check_saddlepoint",&check,NULL);CHKERRQ(ierr);
2840064a4176SStefano Zampini       if (check) {
2841064a4176SStefano Zampini         PetscInt i;
2842064a4176SStefano Zampini 
2843064a4176SStefano Zampini         for (i=0;i<nn;i++) {
2844064a4176SStefano Zampini           KSP       kspC;
2845064a4176SStefano Zampini           PC        pc;
2846064a4176SStefano Zampini           Mat       F,pF;
2847064a4176SStefano Zampini           Vec       x,y;
2848064a4176SStefano Zampini           PetscBool isschur,prec = PETSC_TRUE;
2849064a4176SStefano Zampini 
2850064a4176SStefano Zampini           ierr = KSPCreate(PetscObjectComm((PetscObject)ksps[i]),&kspC);CHKERRQ(ierr);
2851064a4176SStefano Zampini           ierr = KSPSetOptionsPrefix(kspC,((PetscObject)ksps[i])->prefix);CHKERRQ(ierr);
2852064a4176SStefano Zampini           ierr = KSPAppendOptionsPrefix(kspC,"check_");CHKERRQ(ierr);
2853064a4176SStefano Zampini           ierr = KSPGetOperators(ksps[i],&F,&pF);CHKERRQ(ierr);
2854064a4176SStefano Zampini           ierr = PetscObjectTypeCompare((PetscObject)F,MATSCHURCOMPLEMENT,&isschur);CHKERRQ(ierr);
2855064a4176SStefano Zampini           if (isschur) {
2856064a4176SStefano Zampini             KSP  kspS,kspS2;
2857064a4176SStefano Zampini             Mat  A00,pA00,A10,A01,A11;
2858064a4176SStefano Zampini             char prefix[256];
2859064a4176SStefano Zampini 
2860064a4176SStefano Zampini             ierr = MatSchurComplementGetKSP(F,&kspS);CHKERRQ(ierr);
2861064a4176SStefano Zampini             ierr = MatSchurComplementGetSubMatrices(F,&A00,&pA00,&A01,&A10,&A11);CHKERRQ(ierr);
2862064a4176SStefano Zampini             ierr = MatCreateSchurComplement(A00,pA00,A01,A10,A11,&F);CHKERRQ(ierr);
2863064a4176SStefano Zampini             ierr = MatSchurComplementGetKSP(F,&kspS2);CHKERRQ(ierr);
2864064a4176SStefano Zampini             ierr = PetscSNPrintf(prefix,sizeof(prefix),"%sschur_",((PetscObject)kspC)->prefix);CHKERRQ(ierr);
2865064a4176SStefano Zampini             ierr = KSPSetOptionsPrefix(kspS2,prefix);CHKERRQ(ierr);
2866064a4176SStefano Zampini             ierr = KSPGetPC(kspS2,&pc);CHKERRQ(ierr);
2867064a4176SStefano Zampini             ierr = PCSetType(pc,PCKSP);CHKERRQ(ierr);
2868064a4176SStefano Zampini             ierr = PCKSPSetKSP(pc,kspS);CHKERRQ(ierr);
2869064a4176SStefano Zampini             ierr = KSPSetFromOptions(kspS2);CHKERRQ(ierr);
2870064a4176SStefano Zampini             ierr = KSPGetPC(kspS2,&pc);CHKERRQ(ierr);
2871064a4176SStefano Zampini             ierr = PCSetUseAmat(pc,PETSC_TRUE);CHKERRQ(ierr);
2872064a4176SStefano Zampini           } else {
2873064a4176SStefano Zampini             ierr = PetscObjectReference((PetscObject)F);CHKERRQ(ierr);
2874064a4176SStefano Zampini           }
2875064a4176SStefano Zampini           ierr = KSPSetFromOptions(kspC);CHKERRQ(ierr);
2876064a4176SStefano Zampini           ierr = PetscOptionsGetBool(NULL,((PetscObject)kspC)->prefix,"-preconditioned",&prec,NULL);CHKERRQ(ierr);
2877064a4176SStefano Zampini           if (prec)  {
2878064a4176SStefano Zampini             ierr = KSPGetPC(ksps[i],&pc);CHKERRQ(ierr);
2879064a4176SStefano Zampini             ierr = KSPSetPC(kspC,pc);CHKERRQ(ierr);
2880064a4176SStefano Zampini           }
2881064a4176SStefano Zampini           ierr = KSPSetOperators(kspC,F,pF);CHKERRQ(ierr);
2882064a4176SStefano Zampini           ierr = MatCreateVecs(F,&x,&y);CHKERRQ(ierr);
2883064a4176SStefano Zampini           ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
2884064a4176SStefano Zampini           ierr = MatMult(F,x,y);CHKERRQ(ierr);
2885064a4176SStefano Zampini           ierr = KSPSolve(kspC,y,x);CHKERRQ(ierr);
2886c0decd05SBarry Smith           ierr = KSPCheckSolve(kspC,pc,x);CHKERRQ(ierr);
2887064a4176SStefano Zampini           ierr = KSPDestroy(&kspC);CHKERRQ(ierr);
2888064a4176SStefano Zampini           ierr = MatDestroy(&F);CHKERRQ(ierr);
2889064a4176SStefano Zampini           ierr = VecDestroy(&x);CHKERRQ(ierr);
2890064a4176SStefano Zampini           ierr = VecDestroy(&y);CHKERRQ(ierr);
2891064a4176SStefano Zampini         }
2892064a4176SStefano Zampini       }
2893e1214c54Sstefano_zampini       ierr = PetscFree(ksps);CHKERRQ(ierr);
2894e1214c54Sstefano_zampini     }
28955a1e936bSStefano Zampini   }
28963425bc38SStefano Zampini   /* return pointers for objects created */
28973425bc38SStefano Zampini   *fetidp_mat = newmat;
28983425bc38SStefano Zampini   *fetidp_pc  = newpc;
28993425bc38SStefano Zampini   PetscFunctionReturn(0);
29003425bc38SStefano Zampini }
29011e6b0712SBarry Smith 
290294ef8ddeSSatish Balay /*@C
29030f202f7eSStefano Zampini  PCBDDCCreateFETIDPOperators - Create FETI-DP operators
29043425bc38SStefano Zampini 
29053425bc38SStefano Zampini    Collective
29063425bc38SStefano Zampini 
29073425bc38SStefano Zampini    Input Parameters:
29081720468bSStefano Zampini +  pc - the BDDC preconditioning context (setup should have been called before)
2909547c9a8eSstefano_zampini .  fully_redundant - true for a fully redundant set of Lagrange multipliers
2910547c9a8eSstefano_zampini -  prefix - optional options database prefix for the objects to be created (can be NULL)
291128509bceSStefano Zampini 
291228509bceSStefano Zampini    Output Parameters:
29130f202f7eSStefano Zampini +  fetidp_mat - shell FETI-DP matrix object
29140f202f7eSStefano Zampini -  fetidp_pc  - shell Dirichlet preconditioner for FETI-DP matrix
291528509bceSStefano Zampini 
29163425bc38SStefano Zampini    Level: developer
29173425bc38SStefano Zampini 
29183425bc38SStefano Zampini    Notes:
29190f202f7eSStefano Zampini      Currently the only operations provided for FETI-DP matrix are MatMult and MatMultTranspose
29203425bc38SStefano Zampini 
29210f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCMatFETIDPGetRHS, PCBDDCMatFETIDPGetSolution
29223425bc38SStefano Zampini @*/
2923547c9a8eSstefano_zampini PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc)
29243425bc38SStefano Zampini {
29253425bc38SStefano Zampini   PetscErrorCode ierr;
29263425bc38SStefano Zampini 
29273425bc38SStefano Zampini   PetscFunctionBegin;
29283425bc38SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
29293425bc38SStefano Zampini   if (pc->setupcalled) {
2930547c9a8eSstefano_zampini     ierr = PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,PetscBool,const char*,Mat*,PC*),(pc,fully_redundant,prefix,fetidp_mat,fetidp_pc));CHKERRQ(ierr);
29316080607fSStefano Zampini   } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"You must call PCSetup_BDDC() first");
29323425bc38SStefano Zampini   PetscFunctionReturn(0);
29333425bc38SStefano Zampini }
29340c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
2935da1bb401SStefano Zampini /*MC
2936da1bb401SStefano Zampini    PCBDDC - Balancing Domain Decomposition by Constraints.
29370c7d97c5SJed Brown 
2938be4a8d98Sprj-    An implementation of the BDDC preconditioner based on the bibliography found below.
293928509bceSStefano Zampini 
294028509bceSStefano Zampini    The matrix to be preconditioned (Pmat) must be of type MATIS.
294128509bceSStefano Zampini 
29420f202f7eSStefano Zampini    Currently works with MATIS matrices with local matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers.
294328509bceSStefano Zampini 
294428509bceSStefano Zampini    It also works with unsymmetric and indefinite problems.
294528509bceSStefano Zampini 
2946b6fdb6dfSStefano 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.
2947b6fdb6dfSStefano Zampini 
2948c7017625SStefano 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).
294928509bceSStefano Zampini 
29500f202f7eSStefano 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()
295130368db7SStefano Zampini    Additional information on dofs can be provided by using PCBDDCSetDofsSplitting(), PCBDDCSetDirichletBoundaries(), PCBDDCSetNeumannBoundaries(), and PCBDDCSetPrimalVerticesIS() and their local counterparts.
295228509bceSStefano Zampini 
29530f202f7eSStefano Zampini    Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). Non-singular modes are retained via SVD.
295428509bceSStefano Zampini 
29550f202f7eSStefano 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.
29560f202f7eSStefano Zampini    User defined change of basis can be passed to PCBDDC by using PCBDDCSetChangeOfBasisMat()
295728509bceSStefano Zampini 
29580f202f7eSStefano Zampini    The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using a MatPartitioning object.
295928509bceSStefano Zampini 
2960df4d28bfSStefano 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.
296128509bceSStefano Zampini 
29620f202f7eSStefano 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.
29630f202f7eSStefano Zampini 
2964d314f959SVaclav Hapla    Options Database Keys (some of them, run with -help for a complete list):
29650f202f7eSStefano Zampini 
2966a2b725a8SWilliam Gropp +    -pc_bddc_use_vertices <true> - use or not vertices in primal space
29670f202f7eSStefano Zampini .    -pc_bddc_use_edges <true> - use or not edges in primal space
29680f202f7eSStefano Zampini .    -pc_bddc_use_faces <false> - use or not faces in primal space
29690f202f7eSStefano Zampini .    -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems
29700f202f7eSStefano Zampini .    -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only)
29710f202f7eSStefano Zampini .    -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested
29720f202f7eSStefano Zampini .    -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1])
297328509bceSStefano Zampini .    -pc_bddc_levels <0> - maximum number of levels for multilevel
29740f202f7eSStefano 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)
29755459c157SBarry 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)
29760f202f7eSStefano Zampini .    -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling
297771f2caa7Sprj- .    -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)
2978bd2a564bSStefano 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)
297928509bceSStefano Zampini -    -pc_bddc_check_level <0> - set verbosity level of debugging output
298028509bceSStefano Zampini 
298128509bceSStefano Zampini    Options for Dirichlet, Neumann or coarse solver can be set with
298228509bceSStefano Zampini .vb
298328509bceSStefano Zampini       -pc_bddc_dirichlet_
298428509bceSStefano Zampini       -pc_bddc_neumann_
298528509bceSStefano Zampini       -pc_bddc_coarse_
298628509bceSStefano Zampini .ve
2987f9ff08acSPierre Jolivet    e.g. -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. PCBDDC uses by default KSPPREONLY and PCLU.
298828509bceSStefano Zampini 
29890f202f7eSStefano Zampini    When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified as
299028509bceSStefano Zampini .vb
2991312be037SStefano Zampini       -pc_bddc_dirichlet_lN_
2992312be037SStefano Zampini       -pc_bddc_neumann_lN_
2993312be037SStefano Zampini       -pc_bddc_coarse_lN_
299428509bceSStefano Zampini .ve
29950f202f7eSStefano Zampini    Note that level number ranges from the finest (0) to the coarsest (N).
29960f202f7eSStefano 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.
29970f202f7eSStefano Zampini .vb
29980f202f7eSStefano Zampini      -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3
29990f202f7eSStefano Zampini .ve
30000f202f7eSStefano 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
3001da1bb401SStefano Zampini 
3002be4a8d98Sprj-    References:
3003*606c0280SSatish Balay +  * - C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149--168, March 2007
3004*606c0280SSatish 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
3005*606c0280SSatish Balay .  * - J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", Computing Volume 83, Issue 2--3, pages 55--85, November 2008
3006*606c0280SSatish 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
3007be4a8d98Sprj- 
3008da1bb401SStefano Zampini    Level: intermediate
3009da1bb401SStefano Zampini 
3010e94cfbe0SPatrick Sanan    Developer Notes:
3011da1bb401SStefano Zampini 
3012da1bb401SStefano Zampini    Contributed by Stefano Zampini
3013da1bb401SStefano Zampini 
3014da1bb401SStefano Zampini .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
3015da1bb401SStefano Zampini M*/
3016b2573a8aSBarry Smith 
30178cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
3018da1bb401SStefano Zampini {
3019da1bb401SStefano Zampini   PetscErrorCode      ierr;
3020da1bb401SStefano Zampini   PC_BDDC             *pcbddc;
3021da1bb401SStefano Zampini 
3022da1bb401SStefano Zampini   PetscFunctionBegin;
3023b00a9115SJed Brown   ierr     = PetscNewLog(pc,&pcbddc);CHKERRQ(ierr);
30243ec1f749SStefano Zampini   pc->data = pcbddc;
3025da1bb401SStefano Zampini 
3026da1bb401SStefano Zampini   /* create PCIS data structure */
3027da1bb401SStefano Zampini   ierr = PCISCreate(pc);CHKERRQ(ierr);
3028da1bb401SStefano Zampini 
30299326c5c6Sstefano_zampini   /* create local graph structure */
30309326c5c6Sstefano_zampini   ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr);
30319326c5c6Sstefano_zampini 
30329326c5c6Sstefano_zampini   /* BDDC nonzero defaults */
30336d9e27e4SStefano Zampini   pcbddc->use_nnsp                  = PETSC_TRUE;
303408a5cf49SStefano Zampini   pcbddc->use_local_adj             = PETSC_TRUE;
303547d04d0dSStefano Zampini   pcbddc->use_vertices              = PETSC_TRUE;
303647d04d0dSStefano Zampini   pcbddc->use_edges                 = PETSC_TRUE;
30373301b35fSStefano Zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
303814f95afaSStefano Zampini   pcbddc->vertex_size               = 1;
3039c703fcc7SStefano Zampini   pcbddc->recompute_topography      = PETSC_TRUE;
304068457ee5SStefano Zampini   pcbddc->coarse_size               = -1;
304185c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
304247d04d0dSStefano Zampini   pcbddc->coarsening_ratio          = 8;
304357de7509SStefano Zampini   pcbddc->coarse_eqs_per_proc       = 1;
304427b6a85dSStefano Zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
30451e0482f5SStefano Zampini   pcbddc->nedfield                  = -1;
30461e0482f5SStefano Zampini   pcbddc->nedglobal                 = PETSC_TRUE;
3047be12c134Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
3048b96c3477SStefano Zampini   pcbddc->sub_schurs_layers         = -1;
3049bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[0]     = 0.0;
3050bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[1]     = 0.0;
3051b7eb3628SStefano Zampini 
3052da1bb401SStefano Zampini   /* function pointers */
3053da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
305493bd9ae7SStefano Zampini   pc->ops->applytranspose      = PCApplyTranspose_BDDC;
3055da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
3056da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
3057da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
30586b78500eSPatrick Sanan   pc->ops->view                = PCView_BDDC;
30590a545947SLisandro Dalcin   pc->ops->applyrichardson     = NULL;
30600a545947SLisandro Dalcin   pc->ops->applysymmetricleft  = NULL;
30610a545947SLisandro Dalcin   pc->ops->applysymmetricright = NULL;
3062534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
3063534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
30649326c5c6Sstefano_zampini   pc->ops->reset               = PCReset_BDDC;
3065da1bb401SStefano Zampini 
3066da1bb401SStefano Zampini   /* composing function */
3067a13144ffSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",PCBDDCSetDiscreteGradient_BDDC);CHKERRQ(ierr);
3068a198735bSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",PCBDDCSetDivergenceMat_BDDC);CHKERRQ(ierr);
3069906d46d4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",PCBDDCSetChangeOfBasisMat_BDDC);CHKERRQ(ierr);
3070674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
307130368db7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",PCBDDCSetPrimalVerticesIS_BDDC);CHKERRQ(ierr);
30723100ebe3SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesLocalIS_C",PCBDDCGetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
30733100ebe3SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesIS_C",PCBDDCGetPrimalVerticesIS_BDDC);CHKERRQ(ierr);
3074bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr);
30752b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC);CHKERRQ(ierr);
3076b8ffe317SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC);CHKERRQ(ierr);
30772b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC);CHKERRQ(ierr);
3078bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
307982ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",PCBDDCSetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
3080bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
308182ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",PCBDDCSetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
3082bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
308382ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",PCBDDCGetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
3084bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
308582ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",PCBDDCGetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
3086bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
308763602bcaSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",PCBDDCSetDofsSplittingLocal_BDDC);CHKERRQ(ierr);
3088bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
3089bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr);
3090bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr);
3091bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr);
3092a06fd7f2SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",PCPreSolveChangeRHS_BDDC);CHKERRQ(ierr);
3093ab8c8b98SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",PCSetCoordinates_BDDC);CHKERRQ(ierr);
3094da1bb401SStefano Zampini   PetscFunctionReturn(0);
3095da1bb401SStefano Zampini }
309643371fb9SStefano Zampini 
309743371fb9SStefano Zampini /*@C
309843371fb9SStefano Zampini  PCBDDCInitializePackage - This function initializes everything in the PCBDDC package. It is called
30998a690491SBarry Smith     from PCInitializePackage().
310043371fb9SStefano Zampini 
310143371fb9SStefano Zampini  Level: developer
310243371fb9SStefano Zampini 
310343371fb9SStefano Zampini  .seealso: PetscInitialize()
310443371fb9SStefano Zampini @*/
310543371fb9SStefano Zampini PetscErrorCode PCBDDCInitializePackage(void)
310643371fb9SStefano Zampini {
310743371fb9SStefano Zampini   PetscErrorCode ierr;
310843371fb9SStefano Zampini   int            i;
310943371fb9SStefano Zampini 
311043371fb9SStefano Zampini   PetscFunctionBegin;
311143371fb9SStefano Zampini   if (PCBDDCPackageInitialized) PetscFunctionReturn(0);
311243371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_TRUE;
311343371fb9SStefano Zampini   ierr = PetscRegisterFinalize(PCBDDCFinalizePackage);CHKERRQ(ierr);
311443371fb9SStefano Zampini 
311543371fb9SStefano Zampini   /* general events */
311643371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCTopo",PC_CLASSID,&PC_BDDC_Topology[0]);CHKERRQ(ierr);
311743371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCLKSP",PC_CLASSID,&PC_BDDC_LocalSolvers[0]);CHKERRQ(ierr);
311843371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCLWor",PC_CLASSID,&PC_BDDC_LocalWork[0]);CHKERRQ(ierr);
311943371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCCorr",PC_CLASSID,&PC_BDDC_CorrectionSetUp[0]);CHKERRQ(ierr);
31208ead10e4SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCASet",PC_CLASSID,&PC_BDDC_ApproxSetUp[0]);CHKERRQ(ierr);
31218ead10e4SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCAApp",PC_CLASSID,&PC_BDDC_ApproxApply[0]);CHKERRQ(ierr);
312243371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCCSet",PC_CLASSID,&PC_BDDC_CoarseSetUp[0]);CHKERRQ(ierr);
312343371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCCKSP",PC_CLASSID,&PC_BDDC_CoarseSolver[0]);CHKERRQ(ierr);
312443371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCAdap",PC_CLASSID,&PC_BDDC_AdaptiveSetUp[0]);CHKERRQ(ierr);
312543371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCScal",PC_CLASSID,&PC_BDDC_Scaling[0]);CHKERRQ(ierr);
312643371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCSchr",PC_CLASSID,&PC_BDDC_Schurs[0]);CHKERRQ(ierr);
312755c176c0SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCDirS",PC_CLASSID,&PC_BDDC_Solves[0][0]);CHKERRQ(ierr);
312855c176c0SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCNeuS",PC_CLASSID,&PC_BDDC_Solves[0][1]);CHKERRQ(ierr);
312955c176c0SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCCoaS",PC_CLASSID,&PC_BDDC_Solves[0][2]);CHKERRQ(ierr);
313043371fb9SStefano Zampini   for (i=1;i<PETSC_PCBDDC_MAXLEVELS;i++) {
313143371fb9SStefano Zampini     char ename[32];
313243371fb9SStefano Zampini 
313343371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCTopo l%02d",i);CHKERRQ(ierr);
313443371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Topology[i]);CHKERRQ(ierr);
313543371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCLKSP l%02d",i);CHKERRQ(ierr);
313643371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_LocalSolvers[i]);CHKERRQ(ierr);
313743371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCLWor l%02d",i);CHKERRQ(ierr);
313843371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_LocalWork[i]);CHKERRQ(ierr);
313943371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCCorr l%02d",i);CHKERRQ(ierr);
314043371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CorrectionSetUp[i]);CHKERRQ(ierr);
31418ead10e4SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCASet l%02d",i);CHKERRQ(ierr);
31428ead10e4SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_ApproxSetUp[i]);CHKERRQ(ierr);
31438ead10e4SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCAApp l%02d",i);CHKERRQ(ierr);
31448ead10e4SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_ApproxApply[i]);CHKERRQ(ierr);
314543371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCCSet l%02d",i);CHKERRQ(ierr);
314643371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CoarseSetUp[i]);CHKERRQ(ierr);
314743371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCCKSP l%02d",i);CHKERRQ(ierr);
314843371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CoarseSolver[i]);CHKERRQ(ierr);
314943371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCAdap l%02d",i);CHKERRQ(ierr);
315043371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_AdaptiveSetUp[i]);CHKERRQ(ierr);
315143371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCScal l%02d",i);CHKERRQ(ierr);
315243371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Scaling[i]);CHKERRQ(ierr);
315343371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCSchr l%02d",i);CHKERRQ(ierr);
315443371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Schurs[i]);CHKERRQ(ierr);
315555c176c0SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCDirS l%02d",i);CHKERRQ(ierr);
315655c176c0SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Solves[i][0]);CHKERRQ(ierr);
315755c176c0SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCNeuS l%02d",i);CHKERRQ(ierr);
315855c176c0SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Solves[i][1]);CHKERRQ(ierr);
315955c176c0SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCCoaS l%02d",i);CHKERRQ(ierr);
316055c176c0SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Solves[i][2]);CHKERRQ(ierr);
316143371fb9SStefano Zampini   }
316243371fb9SStefano Zampini   PetscFunctionReturn(0);
316343371fb9SStefano Zampini }
316443371fb9SStefano Zampini 
316543371fb9SStefano Zampini /*@C
316643371fb9SStefano Zampini  PCBDDCFinalizePackage - This function frees everything from the PCBDDC package. It is
316743371fb9SStefano Zampini     called from PetscFinalize() automatically.
316843371fb9SStefano Zampini 
316943371fb9SStefano Zampini  Level: developer
317043371fb9SStefano Zampini 
317143371fb9SStefano Zampini  .seealso: PetscFinalize()
317243371fb9SStefano Zampini @*/
317343371fb9SStefano Zampini PetscErrorCode PCBDDCFinalizePackage(void)
317443371fb9SStefano Zampini {
317543371fb9SStefano Zampini   PetscFunctionBegin;
317643371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_FALSE;
317743371fb9SStefano Zampini   PetscFunctionReturn(0);
317843371fb9SStefano Zampini }
3179