xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 98921bda46e76d7aaed9e0138c5ff9d0ce93f355)
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     }
16850e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Use vertices: %d (vertex size %D)\n",pcbddc->use_vertices,pcbddc->vertex_size);CHKERRQ(ierr);
169efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use edges: %d\n",pcbddc->use_edges);CHKERRQ(ierr);
170efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use faces: %d\n",pcbddc->use_faces);CHKERRQ(ierr);
171efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use true near null space: %d\n",pcbddc->use_nnsp_true);CHKERRQ(ierr);
172efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use QR for single constraints on cc: %d\n",pcbddc->use_qr_single);CHKERRQ(ierr);
173efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use change of basis on local edge nodes: %d\n",pcbddc->use_change_of_basis);CHKERRQ(ierr);
174efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use change of basis on local face nodes: %d\n",pcbddc->use_change_on_faces);CHKERRQ(ierr);
175efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  User defined change of basis matrix: %d\n",!!pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
176efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Has change of basis matrix: %d\n",!!pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
177efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Eliminate dirichlet boundary dofs: %d\n",pcbddc->eliminate_dirdofs);CHKERRQ(ierr);
178efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Switch on static condensation ops around the interface preconditioner: %d\n",pcbddc->switch_static);CHKERRQ(ierr);
179efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use exact dirichlet trick: %d\n",pcbddc->use_exact_dirichlet_trick);CHKERRQ(ierr);
180bc960bbfSJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"  Interface extension: %s\n",PCBDDCInterfaceExtTypes[pcbddc->interface_extension]);CHKERRQ(ierr);
18150e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Multilevel max levels: %D\n",pcbddc->max_levels);CHKERRQ(ierr);
18250e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Multilevel coarsening ratio: %D\n",pcbddc->coarsening_ratio);CHKERRQ(ierr);
183efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use estimated eigs for coarse problem: %d\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
184efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use deluxe scaling: %d\n",pcbddc->use_deluxe_scaling);CHKERRQ(ierr);
185efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use deluxe zerorows: %d\n",pcbddc->deluxe_zerorows);CHKERRQ(ierr);
186efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use deluxe singlemat: %d\n",pcbddc->deluxe_singlemat);CHKERRQ(ierr);
187efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Rebuild interface graph for Schur principal minors: %d\n",pcbddc->sub_schurs_rebuild);CHKERRQ(ierr);
18850e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Number of dofs' layers for the computation of principal minors: %D\n",pcbddc->sub_schurs_layers);CHKERRQ(ierr);
189efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use user CSR graph to compute successive layers: %d\n",pcbddc->sub_schurs_use_useradj);CHKERRQ(ierr);
190bd2a564bSStefano Zampini     if (pcbddc->adaptive_threshold[1] != pcbddc->adaptive_threshold[0]) {
191bd2a564bSStefano 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);
192bd2a564bSStefano Zampini     } else {
193bd2a564bSStefano 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);
194bd2a564bSStefano Zampini     }
19550e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Min constraints / connected component: %D\n",pcbddc->adaptive_nmin);CHKERRQ(ierr);
19650e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Max constraints / connected component: %D\n",pcbddc->adaptive_nmax);CHKERRQ(ierr);
197efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Invert exact Schur complement for adaptive selection: %d\n",pcbddc->sub_schurs_exact_schur);CHKERRQ(ierr);
198efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Symmetric computation of primal basis functions: %d\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
19950e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Num. Procs. to map coarse adjacency list: %D\n",pcbddc->coarse_adj_red);CHKERRQ(ierr);
20050e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Coarse eqs per proc (significant at the coarsest level): %D\n",pcbddc->coarse_eqs_per_proc);CHKERRQ(ierr);
2018361f951SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Detect disconnected: %d (filter %d)\n",pcbddc->detect_disconnected,pcbddc->detect_disconnected_filter);CHKERRQ(ierr);
202efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Benign subspace trick: %d (change explicit %d)\n",pcbddc->benign_saddle_point,pcbddc->benign_change_explicit);CHKERRQ(ierr);
203efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Benign subspace trick is active: %d\n",pcbddc->benign_have_null);CHKERRQ(ierr);
20415579a77SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Algebraic computation of no-net-flux: %d\n",pcbddc->compute_nonetflux);CHKERRQ(ierr);
205b74ba07aSstefano_zampini     if (!pc->setupcalled) PetscFunctionReturn(0);
2066b78500eSPatrick Sanan 
207fbad9177SStefano Zampini     /* compute interface size */
208e9627c49SStefano Zampini     ierr = VecSet(pcis->vec1_B,1.0);CHKERRQ(ierr);
2090a545947SLisandro Dalcin     ierr = MatCreateVecs(pc->pmat,&counter,NULL);CHKERRQ(ierr);
210e9627c49SStefano Zampini     ierr = VecSet(counter,0.0);CHKERRQ(ierr);
211e9627c49SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
212e9627c49SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
213e9627c49SStefano Zampini     ierr = VecSum(counter,&interface_size);CHKERRQ(ierr);
214e9627c49SStefano Zampini     ierr = VecDestroy(&counter);CHKERRQ(ierr);
215fbad9177SStefano Zampini 
216fbad9177SStefano Zampini     /* compute some statistics on the domain decomposition */
217e9627c49SStefano Zampini     gsum[0] = 1;
218fbad9177SStefano Zampini     gsum[1] = gsum[2] = gsum[3] = gsum[4] = gsum[5] = 0;
219e9627c49SStefano Zampini     loc[0]  = !!pcis->n;
220e9627c49SStefano Zampini     loc[1]  = pcis->n - pcis->n_B;
221e9627c49SStefano Zampini     loc[2]  = pcis->n_B;
222e9627c49SStefano Zampini     loc[3]  = pcbddc->local_primal_size;
223345ecf6cSStefano Zampini     loc[4]  = pcis->n;
224fbad9177SStefano Zampini     loc[5]  = pcbddc->n_local_subs > 0 ? pcbddc->n_local_subs : (pcis->n ? 1 : 0);
225fbad9177SStefano Zampini     loc[6]  = pcbddc->benign_n;
226ffc4695bSBarry Smith     ierr = MPI_Reduce(loc,gsum,6,MPIU_INT64,MPI_SUM,0,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr);
227fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = -1;
228ffc4695bSBarry Smith     ierr = MPI_Reduce(loc,gmax,6,MPIU_INT64,MPI_MAX,0,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr);
229fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = PETSC_MAX_INT;
230ffc4695bSBarry Smith     ierr = MPI_Reduce(loc,gmin,6,MPIU_INT64,MPI_MIN,0,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr);
231ffc4695bSBarry Smith     ierr = MPI_Reduce(&loc[6],&totbenign,1,MPIU_INT64,MPI_SUM,0,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr);
232e9627c49SStefano Zampini     if (pcbddc->coarse_size) {
233e9627c49SStefano Zampini       ratio1 = pc->pmat->rmap->N/(1.*pcbddc->coarse_size);
234e9627c49SStefano Zampini       ratio2 = PetscRealPart(interface_size)/pcbddc->coarse_size;
235e9627c49SStefano Zampini     }
236efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"********************************** STATISTICS AT LEVEL %d **********************************\n",pcbddc->current_level);CHKERRQ(ierr);
23750e0721cSStefano 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);
23850e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Coarsening ratios: all/coarse %D interface/coarse %D\n",(PetscInt)ratio1,(PetscInt)ratio2);CHKERRQ(ierr);
23950e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Active processes : %D\n",(PetscInt)gsum[0]);CHKERRQ(ierr);
24050e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Total subdomains : %D\n",(PetscInt)gsum[5]);CHKERRQ(ierr);
241345ecf6cSStefano Zampini     if (pcbddc->benign_have_null) {
24250e0721cSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"  Benign subs      : %D\n",(PetscInt)totbenign);CHKERRQ(ierr);
243345ecf6cSStefano Zampini     }
24450e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Dofs type        :\tMIN\tMAX\tMEAN\n");CHKERRQ(ierr);
24550e0721cSStefano 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);
24650e0721cSStefano 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);
24750e0721cSStefano 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);
24850e0721cSStefano 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);
24950e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Local     subs   :\t%D\t%D\n"    ,(PetscInt)gmin[5],(PetscInt)gmax[5]);CHKERRQ(ierr);
25015579a77SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
25115579a77SStefano Zampini 
252ffc4695bSBarry Smith     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRMPI(ierr);
25315579a77SStefano Zampini 
25415579a77SStefano Zampini     /* local solvers */
25515579a77SStefano Zampini     ierr = PetscViewerGetSubViewer(viewer,PetscObjectComm((PetscObject)pcbddc->ksp_D),&subviewer);CHKERRQ(ierr);
256dd400576SPatrick Sanan     if (rank == 0) {
25715579a77SStefano Zampini       ierr = PetscViewerASCIIPrintf(subviewer,"--- Interior solver (rank 0)\n");CHKERRQ(ierr);
25815579a77SStefano Zampini       ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr);
25915579a77SStefano Zampini       ierr = KSPView(pcbddc->ksp_D,subviewer);CHKERRQ(ierr);
26015579a77SStefano Zampini       ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr);
26115579a77SStefano Zampini       ierr = PetscViewerASCIIPrintf(subviewer,"--- Correction solver (rank 0)\n");CHKERRQ(ierr);
26215579a77SStefano Zampini       ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr);
26315579a77SStefano Zampini       ierr = KSPView(pcbddc->ksp_R,subviewer);CHKERRQ(ierr);
26415579a77SStefano Zampini       ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr);
26515579a77SStefano Zampini       ierr = PetscViewerFlush(subviewer);CHKERRQ(ierr);
26615579a77SStefano Zampini     }
26715579a77SStefano Zampini     ierr = PetscViewerRestoreSubViewer(viewer,PetscObjectComm((PetscObject)pcbddc->ksp_D),&subviewer);CHKERRQ(ierr);
26827b6a85dSStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
269e9627c49SStefano Zampini 
270fbad9177SStefano Zampini     /* the coarse problem can be handled by a different communicator */
271e9627c49SStefano Zampini     if (pcbddc->coarse_ksp) color = 1;
272e9627c49SStefano Zampini     else color = 0;
273ffc4695bSBarry Smith     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRMPI(ierr);
274e9627c49SStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)pc),&subcomm);CHKERRQ(ierr);
2754b2aedd3SStefano Zampini     ierr = PetscSubcommSetNumber(subcomm,PetscMin(size,2));CHKERRQ(ierr);
276e9627c49SStefano Zampini     ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
277e9627c49SStefano Zampini     ierr = PetscViewerGetSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer);CHKERRQ(ierr);
278e9627c49SStefano Zampini     if (color == 1) {
27915579a77SStefano Zampini       ierr = PetscViewerASCIIPrintf(subviewer,"--- Coarse solver\n");CHKERRQ(ierr);
28015579a77SStefano Zampini       ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr);
281e9627c49SStefano Zampini       ierr = KSPView(pcbddc->coarse_ksp,subviewer);CHKERRQ(ierr);
28215579a77SStefano Zampini       ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr);
283e9627c49SStefano Zampini       ierr = PetscViewerFlush(subviewer);CHKERRQ(ierr);
284e9627c49SStefano Zampini     }
285e9627c49SStefano Zampini     ierr = PetscViewerRestoreSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer);CHKERRQ(ierr);
286e9627c49SStefano Zampini     ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
287e9627c49SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
288e9627c49SStefano Zampini   }
2896b78500eSPatrick Sanan   PetscFunctionReturn(0);
2906b78500eSPatrick Sanan }
291a13144ffSStefano Zampini 
2921e0482f5SStefano Zampini static PetscErrorCode PCBDDCSetDiscreteGradient_BDDC(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
293a13144ffSStefano Zampini {
294a13144ffSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
295a13144ffSStefano Zampini   PetscErrorCode ierr;
296a13144ffSStefano Zampini 
297a13144ffSStefano Zampini   PetscFunctionBegin;
298a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)G);CHKERRQ(ierr);
299a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
300a13144ffSStefano Zampini   pcbddc->discretegradient = G;
301a13144ffSStefano Zampini   pcbddc->nedorder         = order > 0 ? order : -order;
302495a2a07SStefano Zampini   pcbddc->nedfield         = field;
3031e0482f5SStefano Zampini   pcbddc->nedglobal        = global;
3041e0482f5SStefano Zampini   pcbddc->conforming       = conforming;
305a13144ffSStefano Zampini   PetscFunctionReturn(0);
306a13144ffSStefano Zampini }
307a13144ffSStefano Zampini 
308a13144ffSStefano Zampini /*@
309a13144ffSStefano Zampini  PCBDDCSetDiscreteGradient - Sets the discrete gradient
310a13144ffSStefano Zampini 
311a13144ffSStefano Zampini    Collective on PC
312a13144ffSStefano Zampini 
313a13144ffSStefano Zampini    Input Parameters:
314a13144ffSStefano Zampini +  pc         - the preconditioning context
315a13144ffSStefano Zampini .  G          - the discrete gradient matrix (should be in AIJ format)
316a13144ffSStefano Zampini .  order      - the order of the Nedelec space (1 for the lowest order)
317495a2a07SStefano Zampini .  field      - the field id of the Nedelec dofs (not used if the fields have not been specified)
3181e0482f5SStefano Zampini .  global     - the type of global ordering for the rows of G
319a13144ffSStefano Zampini -  conforming - whether the mesh is conforming or not
320a13144ffSStefano Zampini 
321a13144ffSStefano Zampini    Level: advanced
322a13144ffSStefano Zampini 
32395452b02SPatrick Sanan    Notes:
32495452b02SPatrick Sanan     The discrete gradient matrix G is used to analyze the subdomain edges, and it should not contain any zero entry.
325495a2a07SStefano Zampini           For variable order spaces, the order should be set to zero.
3261e0482f5SStefano Zampini           If global is true, the rows of G should be given in global ordering for the whole dofs;
3271e0482f5SStefano Zampini           if false, the ordering should be global for the Nedelec field.
3281e0482f5SStefano 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
3291e0482f5SStefano Zampini           and geid the one for the Nedelec field.
330a13144ffSStefano Zampini 
331495a2a07SStefano Zampini .seealso: PCBDDC,PCBDDCSetDofsSplitting(),PCBDDCSetDofsSplittingLocal()
332a13144ffSStefano Zampini @*/
3331e0482f5SStefano Zampini PetscErrorCode PCBDDCSetDiscreteGradient(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
334a13144ffSStefano Zampini {
335a13144ffSStefano Zampini   PetscErrorCode ierr;
336a13144ffSStefano Zampini 
337a13144ffSStefano Zampini   PetscFunctionBegin;
338a13144ffSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
339a13144ffSStefano Zampini   PetscValidHeaderSpecific(G,MAT_CLASSID,2);
340a13144ffSStefano Zampini   PetscValidLogicalCollectiveInt(pc,order,3);
3411e0482f5SStefano Zampini   PetscValidLogicalCollectiveInt(pc,field,4);
3421e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc,global,5);
3431e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc,conforming,6);
3441e0482f5SStefano Zampini   PetscCheckSameComm(pc,1,G,2);
3451e0482f5SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDiscreteGradient_C",(PC,Mat,PetscInt,PetscInt,PetscBool,PetscBool),(pc,G,order,field,global,conforming));CHKERRQ(ierr);
346a13144ffSStefano Zampini   PetscFunctionReturn(0);
347a13144ffSStefano Zampini }
348a13144ffSStefano Zampini 
3498ae0ca82SStefano Zampini static PetscErrorCode PCBDDCSetDivergenceMat_BDDC(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
350a198735bSStefano Zampini {
351a198735bSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
352a198735bSStefano Zampini   PetscErrorCode ierr;
3536b78500eSPatrick Sanan 
354a198735bSStefano Zampini   PetscFunctionBegin;
355a198735bSStefano Zampini   ierr = PetscObjectReference((PetscObject)divudotp);CHKERRQ(ierr);
356a198735bSStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
357a198735bSStefano Zampini   pcbddc->divudotp = divudotp;
3588ae0ca82SStefano Zampini   pcbddc->divudotp_trans = trans;
359a198735bSStefano Zampini   pcbddc->compute_nonetflux = PETSC_TRUE;
360a198735bSStefano Zampini   if (vl2l) {
361a198735bSStefano Zampini     ierr = PetscObjectReference((PetscObject)vl2l);CHKERRQ(ierr);
362fa23a32eSStefano Zampini     ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
363a198735bSStefano Zampini     pcbddc->divudotp_vl2l = vl2l;
364a198735bSStefano Zampini   }
365a198735bSStefano Zampini   PetscFunctionReturn(0);
366a198735bSStefano Zampini }
3673d996552SStefano Zampini 
368a198735bSStefano Zampini /*@
369a198735bSStefano Zampini  PCBDDCSetDivergenceMat - Sets the linear operator representing \int_\Omega \div {\bf u} \cdot p dx
370a198735bSStefano Zampini 
371a198735bSStefano Zampini    Collective on PC
372a198735bSStefano Zampini 
373a198735bSStefano Zampini    Input Parameters:
374a198735bSStefano Zampini +  pc - the preconditioning context
375a198735bSStefano Zampini .  divudotp - the matrix (must be of type MATIS)
3768ae0ca82SStefano Zampini .  trans - if trans if false (resp. true), then pressures are in the test (trial) space and velocities are in the trial (test) space.
37705a3bf82SStefano 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
378a198735bSStefano Zampini 
379a198735bSStefano Zampini    Level: advanced
380a198735bSStefano Zampini 
38195452b02SPatrick Sanan    Notes:
38295452b02SPatrick Sanan     This auxiliary matrix is used to compute quadrature weights representing the net-flux across subdomain boundaries
38305a3bf82SStefano Zampini           If vl2l is NULL, the local ordering for velocities in divudotp should match that of the preconditioning matrix
384a198735bSStefano Zampini 
385a198735bSStefano Zampini .seealso: PCBDDC
386a198735bSStefano Zampini @*/
3878ae0ca82SStefano Zampini PetscErrorCode PCBDDCSetDivergenceMat(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
388a198735bSStefano Zampini {
389a198735bSStefano Zampini   PetscBool      ismatis;
390a198735bSStefano Zampini   PetscErrorCode ierr;
391a198735bSStefano Zampini 
392a198735bSStefano Zampini   PetscFunctionBegin;
393a198735bSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
394a198735bSStefano Zampini   PetscValidHeaderSpecific(divudotp,MAT_CLASSID,2);
395a198735bSStefano Zampini   PetscCheckSameComm(pc,1,divudotp,2);
3968ae0ca82SStefano Zampini   PetscValidLogicalCollectiveBool(pc,trans,3);
3971b24a7afSStefano Zampini   if (vl2l) PetscValidHeaderSpecific(vl2l,IS_CLASSID,4);
398a198735bSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)divudotp,MATIS,&ismatis);CHKERRQ(ierr);
399a198735bSStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Divergence matrix needs to be of type MATIS");
4008ae0ca82SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDivergenceMat_C",(PC,Mat,PetscBool,IS),(pc,divudotp,trans,vl2l));CHKERRQ(ierr);
401a198735bSStefano Zampini   PetscFunctionReturn(0);
402a198735bSStefano Zampini }
4032d505d7fSStefano Zampini 
4041dd7afcfSStefano Zampini static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change, PetscBool interior)
405b9b85e73SStefano Zampini {
406b9b85e73SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
407b9b85e73SStefano Zampini   PetscErrorCode ierr;
408b9b85e73SStefano Zampini 
409b9b85e73SStefano Zampini   PetscFunctionBegin;
410b9b85e73SStefano Zampini   ierr = PetscObjectReference((PetscObject)change);CHKERRQ(ierr);
41156282151SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
412b9b85e73SStefano Zampini   pcbddc->user_ChangeOfBasisMatrix = change;
4131dd7afcfSStefano Zampini   pcbddc->change_interior = interior;
414b9b85e73SStefano Zampini   PetscFunctionReturn(0);
415b9b85e73SStefano Zampini }
416b9b85e73SStefano Zampini /*@
417906d46d4SStefano Zampini  PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs
418b9b85e73SStefano Zampini 
419b9b85e73SStefano Zampini    Collective on PC
420b9b85e73SStefano Zampini 
421b9b85e73SStefano Zampini    Input Parameters:
422b9b85e73SStefano Zampini +  pc - the preconditioning context
4231dd7afcfSStefano Zampini .  change - the change of basis matrix
4241dd7afcfSStefano Zampini -  interior - whether or not the change of basis modifies interior dofs
425b9b85e73SStefano Zampini 
426b9b85e73SStefano Zampini    Level: intermediate
427b9b85e73SStefano Zampini 
428b9b85e73SStefano Zampini    Notes:
429b9b85e73SStefano Zampini 
430b9b85e73SStefano Zampini .seealso: PCBDDC
431b9b85e73SStefano Zampini @*/
4321dd7afcfSStefano Zampini PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change, PetscBool interior)
433b9b85e73SStefano Zampini {
434b9b85e73SStefano Zampini   PetscErrorCode ierr;
435b9b85e73SStefano Zampini 
436b9b85e73SStefano Zampini   PetscFunctionBegin;
437b9b85e73SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
438b9b85e73SStefano Zampini   PetscValidHeaderSpecific(change,MAT_CLASSID,2);
439906d46d4SStefano Zampini   PetscCheckSameComm(pc,1,change,2);
440906d46d4SStefano Zampini   if (pc->mat) {
441906d46d4SStefano Zampini     PetscInt rows_c,cols_c,rows,cols;
442906d46d4SStefano Zampini     ierr = MatGetSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
443906d46d4SStefano Zampini     ierr = MatGetSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
444*98921bdaSJacob Faibussowitsch     if (rows_c != rows) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of rows for change of basis matrix! %D != %D",rows_c,rows);
445*98921bdaSJacob Faibussowitsch     if (cols_c != cols) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of columns for change of basis matrix! %D != %D",cols_c,cols);
446906d46d4SStefano Zampini     ierr = MatGetLocalSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
447906d46d4SStefano Zampini     ierr = MatGetLocalSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
448*98921bdaSJacob Faibussowitsch     if (rows_c != rows) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of local rows for change of basis matrix! %D != %D",rows_c,rows);
449*98921bdaSJacob Faibussowitsch     if (cols_c != cols) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of local columns for change of basis matrix! %D != %D",cols_c,cols);
450906d46d4SStefano Zampini   }
4511dd7afcfSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetChangeOfBasisMat_C",(PC,Mat,PetscBool),(pc,change,interior));CHKERRQ(ierr);
452b9b85e73SStefano Zampini   PetscFunctionReturn(0);
453b9b85e73SStefano Zampini }
4542d505d7fSStefano Zampini 
45530368db7SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesIS_BDDC(PC pc, IS PrimalVertices)
45630368db7SStefano Zampini {
45730368db7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
45856282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
45930368db7SStefano Zampini   PetscErrorCode ierr;
46030368db7SStefano Zampini 
46130368db7SStefano Zampini   PetscFunctionBegin;
46256282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
46356282151SStefano Zampini   if (pcbddc->user_primal_vertices) {
46456282151SStefano Zampini     ierr = ISEqual(PrimalVertices,pcbddc->user_primal_vertices,&isequal);CHKERRQ(ierr);
46556282151SStefano Zampini   }
46630368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
46730368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
46830368db7SStefano Zampini   pcbddc->user_primal_vertices = PrimalVertices;
46956282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
47030368db7SStefano Zampini   PetscFunctionReturn(0);
47130368db7SStefano Zampini }
472ab8c8b98SStefano Zampini 
47330368db7SStefano Zampini /*@
47430368db7SStefano Zampini  PCBDDCSetPrimalVerticesIS - Set additional user defined primal vertices in PCBDDC
47530368db7SStefano Zampini 
47630368db7SStefano Zampini    Collective
47730368db7SStefano Zampini 
47830368db7SStefano Zampini    Input Parameters:
47930368db7SStefano Zampini +  pc - the preconditioning context
48030368db7SStefano Zampini -  PrimalVertices - index set of primal vertices in global numbering (can be empty)
48130368db7SStefano Zampini 
48230368db7SStefano Zampini    Level: intermediate
48330368db7SStefano Zampini 
48430368db7SStefano Zampini    Notes:
48530368db7SStefano Zampini      Any process can list any global node
48630368db7SStefano Zampini 
4873100ebe3SStefano Zampini .seealso: PCBDDC, PCBDDCGetPrimalVerticesIS(), PCBDDCSetPrimalVerticesLocalIS(), PCBDDCGetPrimalVerticesLocalIS()
48830368db7SStefano Zampini @*/
48930368db7SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesIS(PC pc, IS PrimalVertices)
49030368db7SStefano Zampini {
49130368db7SStefano Zampini   PetscErrorCode ierr;
49230368db7SStefano Zampini 
49330368db7SStefano Zampini   PetscFunctionBegin;
49430368db7SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
49530368db7SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
49630368db7SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
49730368db7SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
49830368db7SStefano Zampini   PetscFunctionReturn(0);
49930368db7SStefano Zampini }
5002d505d7fSStefano Zampini 
5013100ebe3SStefano Zampini static PetscErrorCode PCBDDCGetPrimalVerticesIS_BDDC(PC pc, IS *is)
5023100ebe3SStefano Zampini {
5033100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC*)pc->data;
5043100ebe3SStefano Zampini 
5053100ebe3SStefano Zampini   PetscFunctionBegin;
5063100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices;
5073100ebe3SStefano Zampini   PetscFunctionReturn(0);
5083100ebe3SStefano Zampini }
5093100ebe3SStefano Zampini 
5103100ebe3SStefano Zampini /*@
5113100ebe3SStefano Zampini  PCBDDCGetPrimalVerticesIS - Get user defined primal vertices set with PCBDDCSetPrimalVerticesIS()
5123100ebe3SStefano Zampini 
5133100ebe3SStefano Zampini    Collective
5143100ebe3SStefano Zampini 
5153100ebe3SStefano Zampini    Input Parameters:
5163100ebe3SStefano Zampini .  pc - the preconditioning context
5173100ebe3SStefano Zampini 
5183100ebe3SStefano Zampini    Output Parameters:
5193100ebe3SStefano Zampini .  is - index set of primal vertices in global numbering (NULL if not set)
5203100ebe3SStefano Zampini 
5213100ebe3SStefano Zampini    Level: intermediate
5223100ebe3SStefano Zampini 
5233100ebe3SStefano Zampini    Notes:
5243100ebe3SStefano Zampini 
5253100ebe3SStefano Zampini .seealso: PCBDDC, PCBDDCSetPrimalVerticesIS(), PCBDDCSetPrimalVerticesLocalIS(), PCBDDCGetPrimalVerticesLocalIS()
5263100ebe3SStefano Zampini @*/
5273100ebe3SStefano Zampini PetscErrorCode PCBDDCGetPrimalVerticesIS(PC pc, IS *is)
5283100ebe3SStefano Zampini {
5293100ebe3SStefano Zampini   PetscErrorCode ierr;
5303100ebe3SStefano Zampini 
5313100ebe3SStefano Zampini   PetscFunctionBegin;
5323100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5333100ebe3SStefano Zampini   PetscValidPointer(is,2);
5343100ebe3SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetPrimalVerticesIS_C",(PC,IS*),(pc,is));CHKERRQ(ierr);
5353100ebe3SStefano Zampini   PetscFunctionReturn(0);
5363100ebe3SStefano Zampini }
5373100ebe3SStefano Zampini 
538674ae819SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
539674ae819SStefano Zampini {
540674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
54156282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
542674ae819SStefano Zampini   PetscErrorCode ierr;
5431e6b0712SBarry Smith 
544674ae819SStefano Zampini   PetscFunctionBegin;
54556282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
54656282151SStefano Zampini   if (pcbddc->user_primal_vertices_local) {
54756282151SStefano Zampini     ierr = ISEqual(PrimalVertices,pcbddc->user_primal_vertices_local,&isequal);CHKERRQ(ierr);
54856282151SStefano Zampini   }
549674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
55030368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
55130368db7SStefano Zampini   pcbddc->user_primal_vertices_local = PrimalVertices;
55256282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
553674ae819SStefano Zampini   PetscFunctionReturn(0);
554674ae819SStefano Zampini }
5553100ebe3SStefano Zampini 
556674ae819SStefano Zampini /*@
55728509bceSStefano Zampini  PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in PCBDDC
558674ae819SStefano Zampini 
55917eb1463SStefano Zampini    Collective
560674ae819SStefano Zampini 
561674ae819SStefano Zampini    Input Parameters:
562674ae819SStefano Zampini +  pc - the preconditioning context
56317eb1463SStefano Zampini -  PrimalVertices - index set of primal vertices in local numbering (can be empty)
564674ae819SStefano Zampini 
565674ae819SStefano Zampini    Level: intermediate
566674ae819SStefano Zampini 
567674ae819SStefano Zampini    Notes:
568674ae819SStefano Zampini 
5693100ebe3SStefano Zampini .seealso: PCBDDC, PCBDDCSetPrimalVerticesIS(), PCBDDCGetPrimalVerticesIS(), PCBDDCGetPrimalVerticesLocalIS()
570674ae819SStefano Zampini @*/
571674ae819SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
572674ae819SStefano Zampini {
573674ae819SStefano Zampini   PetscErrorCode ierr;
574674ae819SStefano Zampini 
575674ae819SStefano Zampini   PetscFunctionBegin;
576674ae819SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
577674ae819SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
57817eb1463SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
579674ae819SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
580674ae819SStefano Zampini   PetscFunctionReturn(0);
581674ae819SStefano Zampini }
5822d505d7fSStefano Zampini 
5833100ebe3SStefano Zampini static PetscErrorCode PCBDDCGetPrimalVerticesLocalIS_BDDC(PC pc, IS *is)
5843100ebe3SStefano Zampini {
5853100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC*)pc->data;
5863100ebe3SStefano Zampini 
5873100ebe3SStefano Zampini   PetscFunctionBegin;
5883100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices_local;
5893100ebe3SStefano Zampini   PetscFunctionReturn(0);
5903100ebe3SStefano Zampini }
5913100ebe3SStefano Zampini 
5923100ebe3SStefano Zampini /*@
5933100ebe3SStefano Zampini  PCBDDCGetPrimalVerticesLocalIS - Get user defined primal vertices set with PCBDDCSetPrimalVerticesLocalIS()
5943100ebe3SStefano Zampini 
5953100ebe3SStefano Zampini    Collective
5963100ebe3SStefano Zampini 
5973100ebe3SStefano Zampini    Input Parameters:
5983100ebe3SStefano Zampini .  pc - the preconditioning context
5993100ebe3SStefano Zampini 
6003100ebe3SStefano Zampini    Output Parameters:
6013100ebe3SStefano Zampini .  is - index set of primal vertices in local numbering (NULL if not set)
6023100ebe3SStefano Zampini 
6033100ebe3SStefano Zampini    Level: intermediate
6043100ebe3SStefano Zampini 
6053100ebe3SStefano Zampini    Notes:
6063100ebe3SStefano Zampini 
6073100ebe3SStefano Zampini .seealso: PCBDDC, PCBDDCSetPrimalVerticesIS(), PCBDDCGetPrimalVerticesIS(), PCBDDCSetPrimalVerticesLocalIS()
6083100ebe3SStefano Zampini @*/
6093100ebe3SStefano Zampini PetscErrorCode PCBDDCGetPrimalVerticesLocalIS(PC pc, IS *is)
6103100ebe3SStefano Zampini {
6113100ebe3SStefano Zampini   PetscErrorCode ierr;
6123100ebe3SStefano Zampini 
6133100ebe3SStefano Zampini   PetscFunctionBegin;
6143100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
6153100ebe3SStefano Zampini   PetscValidPointer(is,2);
6163100ebe3SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetPrimalVerticesLocalIS_C",(PC,IS*),(pc,is));CHKERRQ(ierr);
6173100ebe3SStefano Zampini   PetscFunctionReturn(0);
6183100ebe3SStefano Zampini }
6193100ebe3SStefano Zampini 
6204fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k)
6214fad6a16SStefano Zampini {
6224fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
6234fad6a16SStefano Zampini 
6244fad6a16SStefano Zampini   PetscFunctionBegin;
6254fad6a16SStefano Zampini   pcbddc->coarsening_ratio = k;
6264fad6a16SStefano Zampini   PetscFunctionReturn(0);
6274fad6a16SStefano Zampini }
6281e6b0712SBarry Smith 
6294fad6a16SStefano Zampini /*@
63028509bceSStefano Zampini  PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel
6314fad6a16SStefano Zampini 
6324fad6a16SStefano Zampini    Logically collective on PC
6334fad6a16SStefano Zampini 
6344fad6a16SStefano Zampini    Input Parameters:
6354fad6a16SStefano Zampini +  pc - the preconditioning context
63628509bceSStefano Zampini -  k - coarsening ratio (H/h at the coarser level)
6374fad6a16SStefano Zampini 
6380f202f7eSStefano Zampini    Options Database Keys:
6390f202f7eSStefano Zampini .    -pc_bddc_coarsening_ratio
6404fad6a16SStefano Zampini 
6414fad6a16SStefano Zampini    Level: intermediate
6424fad6a16SStefano Zampini 
6434fad6a16SStefano Zampini    Notes:
6440f202f7eSStefano Zampini      Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level
6454fad6a16SStefano Zampini 
6460f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetLevels()
6474fad6a16SStefano Zampini @*/
6484fad6a16SStefano Zampini PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k)
6494fad6a16SStefano Zampini {
6504fad6a16SStefano Zampini   PetscErrorCode ierr;
6514fad6a16SStefano Zampini 
6524fad6a16SStefano Zampini   PetscFunctionBegin;
6534fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
6542b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,k,2);
6554fad6a16SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));CHKERRQ(ierr);
6564fad6a16SStefano Zampini   PetscFunctionReturn(0);
6574fad6a16SStefano Zampini }
6582b510759SStefano Zampini 
659b8ffe317SStefano Zampini /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */
660b8ffe317SStefano Zampini static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc,PetscBool flg)
661b8ffe317SStefano Zampini {
662b8ffe317SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
663b8ffe317SStefano Zampini 
664b8ffe317SStefano Zampini   PetscFunctionBegin;
66585c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = flg;
666b8ffe317SStefano Zampini   PetscFunctionReturn(0);
667b8ffe317SStefano Zampini }
668b8ffe317SStefano Zampini 
669b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool flg)
6702b510759SStefano Zampini {
6712b510759SStefano Zampini   PetscErrorCode ierr;
6722b510759SStefano Zampini 
6732b510759SStefano Zampini   PetscFunctionBegin;
6742b510759SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
675b8ffe317SStefano Zampini   PetscValidLogicalCollectiveBool(pc,flg,2);
676b8ffe317SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetUseExactDirichlet_C",(PC,PetscBool),(pc,flg));CHKERRQ(ierr);
6772b510759SStefano Zampini   PetscFunctionReturn(0);
6782b510759SStefano Zampini }
6791e6b0712SBarry Smith 
6802b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc,PetscInt level)
6814fad6a16SStefano Zampini {
6824fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
6834fad6a16SStefano Zampini 
6844fad6a16SStefano Zampini   PetscFunctionBegin;
6852b510759SStefano Zampini   pcbddc->current_level = level;
6864fad6a16SStefano Zampini   PetscFunctionReturn(0);
6874fad6a16SStefano Zampini }
6881e6b0712SBarry Smith 
689b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level)
690b8ffe317SStefano Zampini {
691b8ffe317SStefano Zampini   PetscErrorCode ierr;
692b8ffe317SStefano Zampini 
693b8ffe317SStefano Zampini   PetscFunctionBegin;
694b8ffe317SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
695b8ffe317SStefano Zampini   PetscValidLogicalCollectiveInt(pc,level,2);
696b8ffe317SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLevel_C",(PC,PetscInt),(pc,level));CHKERRQ(ierr);
697b8ffe317SStefano Zampini   PetscFunctionReturn(0);
698b8ffe317SStefano Zampini }
699b8ffe317SStefano Zampini 
7002b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc,PetscInt levels)
7012b510759SStefano Zampini {
7022b510759SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
7032b510759SStefano Zampini 
7042b510759SStefano Zampini   PetscFunctionBegin;
705*98921bdaSJacob Faibussowitsch   if (levels > PETSC_PCBDDC_MAXLEVELS-1) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Maximum number of additional levels for BDDC is %d",PETSC_PCBDDC_MAXLEVELS-1);
7062b510759SStefano Zampini   pcbddc->max_levels = levels;
7072b510759SStefano Zampini   PetscFunctionReturn(0);
7082b510759SStefano Zampini }
7092b510759SStefano Zampini 
7104fad6a16SStefano Zampini /*@
71137ebbdf7SStefano Zampini  PCBDDCSetLevels - Sets the maximum number of additional levels allowed for multilevel BDDC
7124fad6a16SStefano Zampini 
7134fad6a16SStefano Zampini    Logically collective on PC
7144fad6a16SStefano Zampini 
7154fad6a16SStefano Zampini    Input Parameters:
7164fad6a16SStefano Zampini +  pc - the preconditioning context
71737ebbdf7SStefano Zampini -  levels - the maximum number of levels
7184fad6a16SStefano Zampini 
7190f202f7eSStefano Zampini    Options Database Keys:
7200f202f7eSStefano Zampini .    -pc_bddc_levels
7214fad6a16SStefano Zampini 
7224fad6a16SStefano Zampini    Level: intermediate
7234fad6a16SStefano Zampini 
7244fad6a16SStefano Zampini    Notes:
72537ebbdf7SStefano Zampini      The default value is 0, that gives the classical two-levels BDDC
7264fad6a16SStefano Zampini 
7270f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetCoarseningRatio()
7284fad6a16SStefano Zampini @*/
7292b510759SStefano Zampini PetscErrorCode PCBDDCSetLevels(PC pc,PetscInt levels)
7304fad6a16SStefano Zampini {
7314fad6a16SStefano Zampini   PetscErrorCode ierr;
7324fad6a16SStefano Zampini 
7334fad6a16SStefano Zampini   PetscFunctionBegin;
7344fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
7352b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,levels,2);
7362b510759SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLevels_C",(PC,PetscInt),(pc,levels));CHKERRQ(ierr);
7374fad6a16SStefano Zampini   PetscFunctionReturn(0);
7384fad6a16SStefano Zampini }
7391e6b0712SBarry Smith 
7403b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
7413b03a366Sstefano_zampini {
7423b03a366Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
74356282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
7443b03a366Sstefano_zampini   PetscErrorCode ierr;
7453b03a366Sstefano_zampini 
7463b03a366Sstefano_zampini   PetscFunctionBegin;
74756282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
74856282151SStefano Zampini   if (pcbddc->DirichletBoundaries) {
74956282151SStefano Zampini     ierr = ISEqual(DirichletBoundaries,pcbddc->DirichletBoundaries,&isequal);CHKERRQ(ierr);
75056282151SStefano Zampini   }
751a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
752785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
7533b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
75436e030ebSStefano Zampini   pcbddc->DirichletBoundaries = DirichletBoundaries;
75556282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7563b03a366Sstefano_zampini   PetscFunctionReturn(0);
7573b03a366Sstefano_zampini }
7581e6b0712SBarry Smith 
7593b03a366Sstefano_zampini /*@
76028509bceSStefano Zampini  PCBDDCSetDirichletBoundaries - Set IS defining Dirichlet boundaries for the global problem.
7613b03a366Sstefano_zampini 
762785d1243SStefano Zampini    Collective
7633b03a366Sstefano_zampini 
7643b03a366Sstefano_zampini    Input Parameters:
7653b03a366Sstefano_zampini +  pc - the preconditioning context
766785d1243SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries
7673b03a366Sstefano_zampini 
7683b03a366Sstefano_zampini    Level: intermediate
7693b03a366Sstefano_zampini 
7700f202f7eSStefano Zampini    Notes:
7710f202f7eSStefano Zampini      Provide the information if you used MatZeroRows/Columns routines. Any process can list any global node
7723b03a366Sstefano_zampini 
7730f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetDirichletBoundariesLocal(), MatZeroRows(), MatZeroRowsColumns()
7743b03a366Sstefano_zampini @*/
7753b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
7763b03a366Sstefano_zampini {
7773b03a366Sstefano_zampini   PetscErrorCode ierr;
7783b03a366Sstefano_zampini 
7793b03a366Sstefano_zampini   PetscFunctionBegin;
7803b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
781674ae819SStefano Zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
782785d1243SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
7833b03a366Sstefano_zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
7843b03a366Sstefano_zampini   PetscFunctionReturn(0);
7853b03a366Sstefano_zampini }
7861e6b0712SBarry Smith 
78782ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc,IS DirichletBoundaries)
7883b03a366Sstefano_zampini {
7893b03a366Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
79056282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
7913b03a366Sstefano_zampini   PetscErrorCode ierr;
7923b03a366Sstefano_zampini 
7933b03a366Sstefano_zampini   PetscFunctionBegin;
79456282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
79556282151SStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
79656282151SStefano Zampini     ierr = ISEqual(DirichletBoundaries,pcbddc->DirichletBoundariesLocal,&isequal);CHKERRQ(ierr);
79756282151SStefano Zampini   }
798a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
799785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
8003b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
801785d1243SStefano Zampini   pcbddc->DirichletBoundariesLocal = DirichletBoundaries;
80256282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
8033b03a366Sstefano_zampini   PetscFunctionReturn(0);
8043b03a366Sstefano_zampini }
8053b03a366Sstefano_zampini 
8063b03a366Sstefano_zampini /*@
80782ba6b80SStefano Zampini  PCBDDCSetDirichletBoundariesLocal - Set IS defining Dirichlet boundaries for the global problem in local ordering.
8083b03a366Sstefano_zampini 
809785d1243SStefano Zampini    Collective
8103b03a366Sstefano_zampini 
8113b03a366Sstefano_zampini    Input Parameters:
8123b03a366Sstefano_zampini +  pc - the preconditioning context
81382ba6b80SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries (in local ordering)
8143b03a366Sstefano_zampini 
8153b03a366Sstefano_zampini    Level: intermediate
8163b03a366Sstefano_zampini 
8173b03a366Sstefano_zampini    Notes:
8183b03a366Sstefano_zampini 
8190f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetDirichletBoundaries(), MatZeroRows(), MatZeroRowsColumns()
8203b03a366Sstefano_zampini @*/
82182ba6b80SStefano Zampini PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc,IS DirichletBoundaries)
8223b03a366Sstefano_zampini {
8233b03a366Sstefano_zampini   PetscErrorCode ierr;
8243b03a366Sstefano_zampini 
8253b03a366Sstefano_zampini   PetscFunctionBegin;
8263b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
8273b03a366Sstefano_zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
82882ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
82982ba6b80SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundariesLocal_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
8303b03a366Sstefano_zampini   PetscFunctionReturn(0);
8313b03a366Sstefano_zampini }
8323b03a366Sstefano_zampini 
83353cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
8340c7d97c5SJed Brown {
8350c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
83656282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
83753cdbc3dSStefano Zampini   PetscErrorCode ierr;
8380c7d97c5SJed Brown 
8390c7d97c5SJed Brown   PetscFunctionBegin;
84056282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
84156282151SStefano Zampini   if (pcbddc->NeumannBoundaries) {
84256282151SStefano Zampini     ierr = ISEqual(NeumannBoundaries,pcbddc->NeumannBoundaries,&isequal);CHKERRQ(ierr);
84356282151SStefano Zampini   }
844a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
845785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
84653cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
84736e030ebSStefano Zampini   pcbddc->NeumannBoundaries = NeumannBoundaries;
84856282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
8490c7d97c5SJed Brown   PetscFunctionReturn(0);
8500c7d97c5SJed Brown }
8511e6b0712SBarry Smith 
85257527edcSJed Brown /*@
85328509bceSStefano Zampini  PCBDDCSetNeumannBoundaries - Set IS defining Neumann boundaries for the global problem.
85457527edcSJed Brown 
855785d1243SStefano Zampini    Collective
85657527edcSJed Brown 
85757527edcSJed Brown    Input Parameters:
85857527edcSJed Brown +  pc - the preconditioning context
859785d1243SStefano Zampini -  NeumannBoundaries - parallel IS defining the Neumann boundaries
86057527edcSJed Brown 
86157527edcSJed Brown    Level: intermediate
86257527edcSJed Brown 
8630f202f7eSStefano Zampini    Notes:
8640f202f7eSStefano Zampini      Any process can list any global node
86557527edcSJed Brown 
8660f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetNeumannBoundariesLocal()
86757527edcSJed Brown @*/
86853cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
8690c7d97c5SJed Brown {
8700c7d97c5SJed Brown   PetscErrorCode ierr;
8710c7d97c5SJed Brown 
8720c7d97c5SJed Brown   PetscFunctionBegin;
8730c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
874674ae819SStefano Zampini   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
875785d1243SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
87653cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
87753cdbc3dSStefano Zampini   PetscFunctionReturn(0);
87853cdbc3dSStefano Zampini }
8791e6b0712SBarry Smith 
88082ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc,IS NeumannBoundaries)
8810c7d97c5SJed Brown {
8820c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
88356282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
8840c7d97c5SJed Brown   PetscErrorCode ierr;
8850c7d97c5SJed Brown 
8860c7d97c5SJed Brown   PetscFunctionBegin;
88756282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
88856282151SStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
88956282151SStefano Zampini     ierr = ISEqual(NeumannBoundaries,pcbddc->NeumannBoundariesLocal,&isequal);CHKERRQ(ierr);
89056282151SStefano Zampini   }
891a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
892785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
8930c7d97c5SJed Brown   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
894785d1243SStefano Zampini   pcbddc->NeumannBoundariesLocal = NeumannBoundaries;
89556282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
8960c7d97c5SJed Brown   PetscFunctionReturn(0);
8970c7d97c5SJed Brown }
8980c7d97c5SJed Brown 
8990c7d97c5SJed Brown /*@
90082ba6b80SStefano Zampini  PCBDDCSetNeumannBoundariesLocal - Set IS defining Neumann boundaries for the global problem in local ordering.
9010c7d97c5SJed Brown 
902785d1243SStefano Zampini    Collective
9030c7d97c5SJed Brown 
9040c7d97c5SJed Brown    Input Parameters:
9050c7d97c5SJed Brown +  pc - the preconditioning context
90682ba6b80SStefano Zampini -  NeumannBoundaries - parallel IS defining the subdomain part of Neumann boundaries (in local ordering)
9070c7d97c5SJed Brown 
9080c7d97c5SJed Brown    Level: intermediate
9090c7d97c5SJed Brown 
9100c7d97c5SJed Brown    Notes:
9110c7d97c5SJed Brown 
9120f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetNeumannBoundaries()
9130c7d97c5SJed Brown @*/
91482ba6b80SStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc,IS NeumannBoundaries)
9150c7d97c5SJed Brown {
9160c7d97c5SJed Brown   PetscErrorCode ierr;
9170c7d97c5SJed Brown 
9180c7d97c5SJed Brown   PetscFunctionBegin;
9190c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
9200c7d97c5SJed Brown   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
92182ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
92282ba6b80SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundariesLocal_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
92353cdbc3dSStefano Zampini   PetscFunctionReturn(0);
92453cdbc3dSStefano Zampini }
92553cdbc3dSStefano Zampini 
926da1bb401SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
927da1bb401SStefano Zampini {
928da1bb401SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
929da1bb401SStefano Zampini 
930da1bb401SStefano Zampini   PetscFunctionBegin;
931da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
932da1bb401SStefano Zampini   PetscFunctionReturn(0);
933da1bb401SStefano Zampini }
9341e6b0712SBarry Smith 
935da1bb401SStefano Zampini /*@
936785d1243SStefano Zampini  PCBDDCGetDirichletBoundaries - Get parallel IS for Dirichlet boundaries
937da1bb401SStefano Zampini 
938785d1243SStefano Zampini    Collective
939785d1243SStefano Zampini 
940785d1243SStefano Zampini    Input Parameters:
941785d1243SStefano Zampini .  pc - the preconditioning context
942785d1243SStefano Zampini 
943785d1243SStefano Zampini    Output Parameters:
944785d1243SStefano Zampini .  DirichletBoundaries - index set defining the Dirichlet boundaries
945785d1243SStefano Zampini 
946785d1243SStefano Zampini    Level: intermediate
947785d1243SStefano Zampini 
9480f202f7eSStefano Zampini    Notes:
9490f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetDirichletBoundaries
950785d1243SStefano Zampini 
951785d1243SStefano Zampini .seealso: PCBDDC
952785d1243SStefano Zampini @*/
953785d1243SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
954785d1243SStefano Zampini {
955785d1243SStefano Zampini   PetscErrorCode ierr;
956785d1243SStefano Zampini 
957785d1243SStefano Zampini   PetscFunctionBegin;
958785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
959785d1243SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
960785d1243SStefano Zampini   PetscFunctionReturn(0);
961785d1243SStefano Zampini }
962785d1243SStefano Zampini 
963785d1243SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc,IS *DirichletBoundaries)
964785d1243SStefano Zampini {
965785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
966785d1243SStefano Zampini 
967785d1243SStefano Zampini   PetscFunctionBegin;
968785d1243SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundariesLocal;
969785d1243SStefano Zampini   PetscFunctionReturn(0);
970785d1243SStefano Zampini }
971785d1243SStefano Zampini 
972da1bb401SStefano Zampini /*@
97382ba6b80SStefano Zampini  PCBDDCGetDirichletBoundariesLocal - Get parallel IS for Dirichlet boundaries (in local ordering)
974da1bb401SStefano Zampini 
975785d1243SStefano Zampini    Collective
976da1bb401SStefano Zampini 
977da1bb401SStefano Zampini    Input Parameters:
97828509bceSStefano Zampini .  pc - the preconditioning context
979da1bb401SStefano Zampini 
980da1bb401SStefano Zampini    Output Parameters:
98128509bceSStefano Zampini .  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
982da1bb401SStefano Zampini 
983da1bb401SStefano Zampini    Level: intermediate
984da1bb401SStefano Zampini 
985da1bb401SStefano Zampini    Notes:
9860f202f7eSStefano 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).
9870f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
988da1bb401SStefano Zampini 
989da1bb401SStefano Zampini .seealso: PCBDDC
990da1bb401SStefano Zampini @*/
99182ba6b80SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc,IS *DirichletBoundaries)
992da1bb401SStefano Zampini {
993da1bb401SStefano Zampini   PetscErrorCode ierr;
994da1bb401SStefano Zampini 
995da1bb401SStefano Zampini   PetscFunctionBegin;
996da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
99782ba6b80SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundariesLocal_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
998da1bb401SStefano Zampini   PetscFunctionReturn(0);
999da1bb401SStefano Zampini }
10001e6b0712SBarry Smith 
100153cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
100253cdbc3dSStefano Zampini {
100353cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
100453cdbc3dSStefano Zampini 
100553cdbc3dSStefano Zampini   PetscFunctionBegin;
100653cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
100753cdbc3dSStefano Zampini   PetscFunctionReturn(0);
100853cdbc3dSStefano Zampini }
10091e6b0712SBarry Smith 
101053cdbc3dSStefano Zampini /*@
1011785d1243SStefano Zampini  PCBDDCGetNeumannBoundaries - Get parallel IS for Neumann boundaries
101253cdbc3dSStefano Zampini 
1013785d1243SStefano Zampini    Collective
1014785d1243SStefano Zampini 
1015785d1243SStefano Zampini    Input Parameters:
1016785d1243SStefano Zampini .  pc - the preconditioning context
1017785d1243SStefano Zampini 
1018785d1243SStefano Zampini    Output Parameters:
1019785d1243SStefano Zampini .  NeumannBoundaries - index set defining the Neumann boundaries
1020785d1243SStefano Zampini 
1021785d1243SStefano Zampini    Level: intermediate
1022785d1243SStefano Zampini 
10230f202f7eSStefano Zampini    Notes:
10240f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetNeumannBoundaries
1025785d1243SStefano Zampini 
1026785d1243SStefano Zampini .seealso: PCBDDC
1027785d1243SStefano Zampini @*/
1028785d1243SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
1029785d1243SStefano Zampini {
1030785d1243SStefano Zampini   PetscErrorCode ierr;
1031785d1243SStefano Zampini 
1032785d1243SStefano Zampini   PetscFunctionBegin;
1033785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1034785d1243SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
1035785d1243SStefano Zampini   PetscFunctionReturn(0);
1036785d1243SStefano Zampini }
1037785d1243SStefano Zampini 
1038785d1243SStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc,IS *NeumannBoundaries)
1039785d1243SStefano Zampini {
1040785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1041785d1243SStefano Zampini 
1042785d1243SStefano Zampini   PetscFunctionBegin;
1043785d1243SStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundariesLocal;
1044785d1243SStefano Zampini   PetscFunctionReturn(0);
1045785d1243SStefano Zampini }
1046785d1243SStefano Zampini 
104753cdbc3dSStefano Zampini /*@
104882ba6b80SStefano Zampini  PCBDDCGetNeumannBoundariesLocal - Get parallel IS for Neumann boundaries (in local ordering)
104953cdbc3dSStefano Zampini 
1050785d1243SStefano Zampini    Collective
105153cdbc3dSStefano Zampini 
105253cdbc3dSStefano Zampini    Input Parameters:
105328509bceSStefano Zampini .  pc - the preconditioning context
105453cdbc3dSStefano Zampini 
105553cdbc3dSStefano Zampini    Output Parameters:
105628509bceSStefano Zampini .  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
105753cdbc3dSStefano Zampini 
105853cdbc3dSStefano Zampini    Level: intermediate
105953cdbc3dSStefano Zampini 
106053cdbc3dSStefano Zampini    Notes:
10610f202f7eSStefano 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).
10620f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
106353cdbc3dSStefano Zampini 
106453cdbc3dSStefano Zampini .seealso: PCBDDC
106553cdbc3dSStefano Zampini @*/
106682ba6b80SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc,IS *NeumannBoundaries)
106753cdbc3dSStefano Zampini {
106853cdbc3dSStefano Zampini   PetscErrorCode ierr;
106953cdbc3dSStefano Zampini 
107053cdbc3dSStefano Zampini   PetscFunctionBegin;
107153cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
107282ba6b80SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundariesLocal_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
10730c7d97c5SJed Brown   PetscFunctionReturn(0);
10740c7d97c5SJed Brown }
10751e6b0712SBarry Smith 
10761a83f524SJed Brown static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
107736e030ebSStefano Zampini {
107836e030ebSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1079da1bb401SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
108056282151SStefano Zampini   PetscBool      same_data = PETSC_FALSE;
1081da1bb401SStefano Zampini   PetscErrorCode ierr;
108236e030ebSStefano Zampini 
108336e030ebSStefano Zampini   PetscFunctionBegin;
10848687889aSStefano Zampini   if (!nvtxs) {
108504194a47SStefano Zampini     if (copymode == PETSC_OWN_POINTER) {
108604194a47SStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
108704194a47SStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
108804194a47SStefano Zampini     }
10898687889aSStefano Zampini     ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
10908687889aSStefano Zampini     PetscFunctionReturn(0);
10918687889aSStefano Zampini   }
109266da6bd7Sstefano_zampini   if (mat_graph->nvtxs == nvtxs && mat_graph->freecsr) { /* we own the data */
109356282151SStefano Zampini     if (mat_graph->xadj == xadj && mat_graph->adjncy == adjncy) same_data = PETSC_TRUE;
109456282151SStefano Zampini     if (!same_data && mat_graph->xadj[nvtxs] == xadj[nvtxs]) {
1095580bdb30SBarry Smith       ierr = PetscArraycmp(xadj,mat_graph->xadj,nvtxs+1,&same_data);CHKERRQ(ierr);
10962d505d7fSStefano Zampini       if (same_data) {
1097580bdb30SBarry Smith         ierr = PetscArraycmp(adjncy,mat_graph->adjncy,xadj[nvtxs],&same_data);CHKERRQ(ierr);
10982d505d7fSStefano Zampini       }
109956282151SStefano Zampini     }
110056282151SStefano Zampini   }
110156282151SStefano Zampini   if (!same_data) {
1102674ae819SStefano Zampini     /* free old CSR */
1103674ae819SStefano Zampini     ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
1104674ae819SStefano Zampini     /* get CSR into graph structure */
1105da1bb401SStefano Zampini     if (copymode == PETSC_COPY_VALUES) {
1106854ce69bSBarry Smith       ierr = PetscMalloc1(nvtxs+1,&mat_graph->xadj);CHKERRQ(ierr);
1107785e854fSJed Brown       ierr = PetscMalloc1(xadj[nvtxs],&mat_graph->adjncy);CHKERRQ(ierr);
1108580bdb30SBarry Smith       ierr = PetscArraycpy(mat_graph->xadj,xadj,nvtxs+1);CHKERRQ(ierr);
1109580bdb30SBarry Smith       ierr = PetscArraycpy(mat_graph->adjncy,adjncy,xadj[nvtxs]);CHKERRQ(ierr);
1110a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1111da1bb401SStefano Zampini     } else if (copymode == PETSC_OWN_POINTER) {
11121a83f524SJed Brown       mat_graph->xadj    = (PetscInt*)xadj;
11131a83f524SJed Brown       mat_graph->adjncy  = (PetscInt*)adjncy;
1114a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1115a1dbd327SStefano Zampini     } else if (copymode == PETSC_USE_POINTER) {
1116a1dbd327SStefano Zampini       mat_graph->xadj    = (PetscInt*)xadj;
1117a1dbd327SStefano Zampini       mat_graph->adjncy  = (PetscInt*)adjncy;
1118a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_FALSE;
1119*98921bdaSJacob Faibussowitsch     } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %D",copymode);
1120575ad6abSStefano Zampini     mat_graph->nvtxs_csr = nvtxs;
112156282151SStefano Zampini     pcbddc->recompute_topography = PETSC_TRUE;
112256282151SStefano Zampini   }
112336e030ebSStefano Zampini   PetscFunctionReturn(0);
112436e030ebSStefano Zampini }
11251e6b0712SBarry Smith 
112636e030ebSStefano Zampini /*@
112754fffbccSStefano Zampini  PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local degrees of freedom.
112836e030ebSStefano Zampini 
112936e030ebSStefano Zampini    Not collective
113036e030ebSStefano Zampini 
113136e030ebSStefano Zampini    Input Parameters:
113254fffbccSStefano Zampini +  pc - the preconditioning context.
113354fffbccSStefano Zampini .  nvtxs - number of local vertices of the graph (i.e., the number of local dofs).
113454fffbccSStefano Zampini .  xadj, adjncy - the connectivity of the dofs in CSR format.
113554fffbccSStefano Zampini -  copymode - supported modes are PETSC_COPY_VALUES, PETSC_USE_POINTER or PETSC_OWN_POINTER.
113636e030ebSStefano Zampini 
113736e030ebSStefano Zampini    Level: intermediate
113836e030ebSStefano Zampini 
113995452b02SPatrick Sanan    Notes:
114095452b02SPatrick Sanan     A dof is considered connected with all local dofs if xadj[dof+1]-xadj[dof] == 1 and adjncy[xadj[dof]] is negative.
114136e030ebSStefano Zampini 
114228509bceSStefano Zampini .seealso: PCBDDC,PetscCopyMode
114336e030ebSStefano Zampini @*/
11441a83f524SJed Brown PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
114536e030ebSStefano Zampini {
11460a545947SLisandro Dalcin   void (*f)(void) = NULL;
114736e030ebSStefano Zampini   PetscErrorCode ierr;
114836e030ebSStefano Zampini 
114936e030ebSStefano Zampini   PetscFunctionBegin;
115036e030ebSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
11518687889aSStefano Zampini   if (nvtxs) {
1152674ae819SStefano Zampini     PetscValidIntPointer(xadj,3);
11531633d1f0SStefano Zampini     if (xadj[nvtxs]) PetscValidIntPointer(adjncy,4);
11548687889aSStefano Zampini   }
11551a83f524SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
1156575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
1157575ad6abSStefano Zampini   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr);
1158575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
1159575ad6abSStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
1160575ad6abSStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
1161da1bb401SStefano Zampini   }
116236e030ebSStefano Zampini   PetscFunctionReturn(0);
116336e030ebSStefano Zampini }
11641e6b0712SBarry Smith 
116563602bcaSStefano Zampini static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
116663602bcaSStefano Zampini {
116763602bcaSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
116863602bcaSStefano Zampini   PetscInt       i;
116956282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
117063602bcaSStefano Zampini   PetscErrorCode ierr;
117163602bcaSStefano Zampini 
117263602bcaSStefano Zampini   PetscFunctionBegin;
117356282151SStefano Zampini   if (pcbddc->n_ISForDofsLocal == n_is) {
117456282151SStefano Zampini     for (i=0;i<n_is;i++) {
117556282151SStefano Zampini       PetscBool isequalt;
117656282151SStefano Zampini       ierr = ISEqual(ISForDofs[i],pcbddc->ISForDofsLocal[i],&isequalt);CHKERRQ(ierr);
117756282151SStefano Zampini       if (!isequalt) break;
117856282151SStefano Zampini     }
117956282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
118056282151SStefano Zampini   }
118156282151SStefano Zampini   for (i=0;i<n_is;i++) {
118256282151SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
118356282151SStefano Zampini   }
118463602bcaSStefano Zampini   /* Destroy ISes if they were already set */
118563602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
118663602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
118763602bcaSStefano Zampini   }
118863602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
1189a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
119063602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
119163602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
119263602bcaSStefano Zampini   }
119363602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
119463602bcaSStefano Zampini   pcbddc->n_ISForDofs = 0;
119563602bcaSStefano Zampini   /* allocate space then set */
1196d02579f5SStefano Zampini   if (n_is) {
1197d02579f5SStefano Zampini     ierr = PetscMalloc1(n_is,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
1198d02579f5SStefano Zampini   }
119963602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
120063602bcaSStefano Zampini     pcbddc->ISForDofsLocal[i] = ISForDofs[i];
120163602bcaSStefano Zampini   }
120263602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = n_is;
120363602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
120456282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
120563602bcaSStefano Zampini   PetscFunctionReturn(0);
120663602bcaSStefano Zampini }
120763602bcaSStefano Zampini 
120863602bcaSStefano Zampini /*@
120963602bcaSStefano Zampini  PCBDDCSetDofsSplittingLocal - Set index sets defining fields of the local subdomain matrix
121063602bcaSStefano Zampini 
121163602bcaSStefano Zampini    Collective
121263602bcaSStefano Zampini 
121363602bcaSStefano Zampini    Input Parameters:
121463602bcaSStefano Zampini +  pc - the preconditioning context
12150f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
12160f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in local ordering
121763602bcaSStefano Zampini 
121863602bcaSStefano Zampini    Level: intermediate
121963602bcaSStefano Zampini 
12200f202f7eSStefano Zampini    Notes:
12210f202f7eSStefano Zampini      n_is should be the same among processes. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
122263602bcaSStefano Zampini 
122363602bcaSStefano Zampini .seealso: PCBDDC
122463602bcaSStefano Zampini @*/
122563602bcaSStefano Zampini PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc,PetscInt n_is, IS ISForDofs[])
122663602bcaSStefano Zampini {
122763602bcaSStefano Zampini   PetscInt       i;
122863602bcaSStefano Zampini   PetscErrorCode ierr;
122963602bcaSStefano Zampini 
123063602bcaSStefano Zampini   PetscFunctionBegin;
123163602bcaSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
123263602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
123363602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
123463602bcaSStefano Zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
123563602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
123663602bcaSStefano Zampini   }
1237e71e7a71SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplittingLocal_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
123863602bcaSStefano Zampini   PetscFunctionReturn(0);
123963602bcaSStefano Zampini }
124063602bcaSStefano Zampini 
12419c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
12429c0446d6SStefano Zampini {
12439c0446d6SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
12449c0446d6SStefano Zampini   PetscInt       i;
124556282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
12469c0446d6SStefano Zampini   PetscErrorCode ierr;
12479c0446d6SStefano Zampini 
12489c0446d6SStefano Zampini   PetscFunctionBegin;
124956282151SStefano Zampini   if (pcbddc->n_ISForDofs == n_is) {
125056282151SStefano Zampini     for (i=0;i<n_is;i++) {
125156282151SStefano Zampini       PetscBool isequalt;
125256282151SStefano Zampini       ierr = ISEqual(ISForDofs[i],pcbddc->ISForDofs[i],&isequalt);CHKERRQ(ierr);
125356282151SStefano Zampini       if (!isequalt) break;
125456282151SStefano Zampini     }
125556282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
125656282151SStefano Zampini   }
125756282151SStefano Zampini   for (i=0;i<n_is;i++) {
125856282151SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
125956282151SStefano Zampini   }
1260da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
12619c0446d6SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
12629c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
12639c0446d6SStefano Zampini   }
1264d11ae9bbSstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
1265a5b23f4aSJose E. Roman   /* last user setting takes precedence -> destroy any other customization */
126663602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
126763602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
126863602bcaSStefano Zampini   }
126963602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
127063602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = 0;
1271da1bb401SStefano Zampini   /* allocate space then set */
1272d02579f5SStefano Zampini   if (n_is) {
1273785e854fSJed Brown     ierr = PetscMalloc1(n_is,&pcbddc->ISForDofs);CHKERRQ(ierr);
1274d02579f5SStefano Zampini   }
12759c0446d6SStefano Zampini   for (i=0;i<n_is;i++) {
1276da1bb401SStefano Zampini     pcbddc->ISForDofs[i] = ISForDofs[i];
12779c0446d6SStefano Zampini   }
12789c0446d6SStefano Zampini   pcbddc->n_ISForDofs = n_is;
127963602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
128056282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
12819c0446d6SStefano Zampini   PetscFunctionReturn(0);
12829c0446d6SStefano Zampini }
12831e6b0712SBarry Smith 
12849c0446d6SStefano Zampini /*@
128563602bcaSStefano Zampini  PCBDDCSetDofsSplitting - Set index sets defining fields of the global matrix
12869c0446d6SStefano Zampini 
128763602bcaSStefano Zampini    Collective
12889c0446d6SStefano Zampini 
12899c0446d6SStefano Zampini    Input Parameters:
12909c0446d6SStefano Zampini +  pc - the preconditioning context
12910f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
12920f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in global ordering
12939c0446d6SStefano Zampini 
12949c0446d6SStefano Zampini    Level: intermediate
12959c0446d6SStefano Zampini 
12960f202f7eSStefano Zampini    Notes:
12970f202f7eSStefano Zampini      Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
12989c0446d6SStefano Zampini 
12999c0446d6SStefano Zampini .seealso: PCBDDC
13009c0446d6SStefano Zampini @*/
13019c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
13029c0446d6SStefano Zampini {
13032b510759SStefano Zampini   PetscInt       i;
13049c0446d6SStefano Zampini   PetscErrorCode ierr;
13059c0446d6SStefano Zampini 
13069c0446d6SStefano Zampini   PetscFunctionBegin;
13079c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
130863602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
13092b510759SStefano Zampini   for (i=0;i<n_is;i++) {
131063602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
1311a011d5a7Sstefano_zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
13122b510759SStefano Zampini   }
13139c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
13149c0446d6SStefano Zampini   PetscFunctionReturn(0);
13159c0446d6SStefano Zampini }
1316906d46d4SStefano Zampini 
1317534831adSStefano Zampini /*
1318534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
1319534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
13209c0446d6SStefano Zampini 
1321534831adSStefano Zampini    Input Parameter:
1322966d8056SPierre Jolivet +  pc - the preconditioner context
1323534831adSStefano Zampini 
1324534831adSStefano Zampini    Application Interface Routine: PCPreSolve()
1325534831adSStefano Zampini 
1326534831adSStefano Zampini    Notes:
1327534831adSStefano Zampini      The interface routine PCPreSolve() is not usually called directly by
1328534831adSStefano Zampini    the user, but instead is called by KSPSolve().
1329534831adSStefano Zampini */
1330534831adSStefano Zampini static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1331534831adSStefano Zampini {
1332534831adSStefano Zampini   PetscErrorCode ierr;
1333534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1334534831adSStefano Zampini   PC_IS          *pcis = (PC_IS*)(pc->data);
13353972b0daSStefano Zampini   Vec            used_vec;
13364df7a6bfSStefano Zampini   PetscBool      iscg = PETSC_FALSE, save_rhs = PETSC_TRUE, benign_correction_computed;
1337534831adSStefano Zampini 
1338534831adSStefano Zampini   PetscFunctionBegin;
13391f4df5f7SStefano Zampini   /* if we are working with CG, one dirichlet solve can be avoided during Krylov iterations */
134085c4d303SStefano Zampini   if (ksp) {
13414df7a6bfSStefano Zampini     PetscBool isgroppcg, ispipecg, ispipelcg, ispipecgrr;
13424df7a6bfSStefano Zampini 
134385c4d303SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPCG,&iscg);CHKERRQ(ierr);
134427b6a85dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPGROPPCG,&isgroppcg);CHKERRQ(ierr);
134527b6a85dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECG,&ispipecg);CHKERRQ(ierr);
13464df7a6bfSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECG,&ispipelcg);CHKERRQ(ierr);
1347f94e96cbSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECGRR,&ispipecgrr);CHKERRQ(ierr);
13484df7a6bfSStefano Zampini     iscg = (PetscBool)(iscg || isgroppcg || ispipecg || ispipelcg || ispipecgrr);
13493bf6e316SStefano Zampini     if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || !iscg || pc->mat != pc->pmat) {
135085c4d303SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
135185c4d303SStefano Zampini     }
135285c4d303SStefano Zampini   }
13533bf6e316SStefano Zampini   if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || pc->mat != pc->pmat) {
1354fc17d649SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
1355fc17d649SStefano Zampini   }
13561f4df5f7SStefano Zampini 
135785c4d303SStefano Zampini   /* Creates parallel work vectors used in presolve */
135862a6ff1dSStefano Zampini   if (!pcbddc->original_rhs) {
135962a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
136062a6ff1dSStefano Zampini   }
136162a6ff1dSStefano Zampini   if (!pcbddc->temp_solution) {
136262a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr);
136362a6ff1dSStefano Zampini   }
13648d00608fSStefano Zampini 
136527b6a85dSStefano Zampini   pcbddc->temp_solution_used = PETSC_FALSE;
13663972b0daSStefano Zampini   if (x) {
13673972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);
13683972b0daSStefano Zampini     used_vec = x;
13698d00608fSStefano Zampini   } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */
13703972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr);
13713972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
13723972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
137327b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
1374266e20e9SStefano Zampini     ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
1375266e20e9SStefano Zampini     save_rhs = PETSC_FALSE;
1376266e20e9SStefano Zampini     pcbddc->eliminate_dirdofs = PETSC_TRUE;
13773972b0daSStefano Zampini   }
13788efcfb23SStefano Zampini 
13798efcfb23SStefano Zampini   /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */
13803972b0daSStefano Zampini   if (ksp) {
1381a0cb1b98SStefano Zampini     /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */
13828efcfb23SStefano Zampini     ierr = KSPGetInitialGuessNonzero(ksp,&pcbddc->ksp_guess_nonzero);CHKERRQ(ierr);
13838efcfb23SStefano Zampini     if (!pcbddc->ksp_guess_nonzero) {
13843972b0daSStefano Zampini       ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
13853972b0daSStefano Zampini     }
13863972b0daSStefano Zampini   }
13873308cffdSStefano Zampini 
13888d00608fSStefano Zampini   pcbddc->rhs_change = PETSC_FALSE;
13893972b0daSStefano Zampini   /* Take into account zeroed rows -> change rhs and store solution removed */
139070c64980SStefano Zampini   if (rhs && pcbddc->eliminate_dirdofs) {
13913975b054SStefano Zampini     IS dirIS = NULL;
13923975b054SStefano Zampini 
1393a07ea27aSStefano Zampini     /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */
13943975b054SStefano Zampini     ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
13953975b054SStefano Zampini     if (dirIS) {
1396906d46d4SStefano Zampini       Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
1397785d1243SStefano Zampini       PetscInt          dirsize,i,*is_indices;
13982b095fd8SStefano Zampini       PetscScalar       *array_x;
13992b095fd8SStefano Zampini       const PetscScalar *array_diagonal;
1400785d1243SStefano Zampini 
14013972b0daSStefano Zampini       ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr);
14023972b0daSStefano Zampini       ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr);
1403e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1404e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1405e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1406e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
140782ba6b80SStefano Zampini       ierr = ISGetLocalSize(dirIS,&dirsize);CHKERRQ(ierr);
14083972b0daSStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
14092b095fd8SStefano Zampini       ierr = VecGetArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
14103972b0daSStefano Zampini       ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
14112fa5cd67SKarl Rupp       for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
14123972b0daSStefano Zampini       ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
14132b095fd8SStefano Zampini       ierr = VecRestoreArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
14143972b0daSStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
1415e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1416e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
14178d00608fSStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
14181b968477SStefano Zampini       ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
14198efcfb23SStefano Zampini     }
1420a07ea27aSStefano Zampini   }
1421b76ba322SStefano Zampini 
14228efcfb23SStefano Zampini   /* remove the computed solution or the initial guess from the rhs */
14238d00608fSStefano Zampini   if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero)) {
142427b6a85dSStefano Zampini     /* save the original rhs */
142527b6a85dSStefano Zampini     if (save_rhs) {
142627b6a85dSStefano Zampini       ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
142727b6a85dSStefano Zampini       save_rhs = PETSC_FALSE;
14288d00608fSStefano Zampini     }
14298d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
14303972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
143127b6a85dSStefano Zampini     ierr = MatMultAdd(pc->mat,used_vec,pcbddc->original_rhs,rhs);CHKERRQ(ierr);
14323972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
14338efcfb23SStefano Zampini     ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr);
143427b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
14357acc28cbSStefano Zampini     if (ksp) {
14367acc28cbSStefano Zampini       ierr = KSPSetInitialGuessNonzero(ksp,PETSC_FALSE);CHKERRQ(ierr);
14377acc28cbSStefano Zampini     }
14383308cffdSStefano Zampini   }
14398efcfb23SStefano Zampini   ierr = VecDestroy(&used_vec);CHKERRQ(ierr);
1440b76ba322SStefano Zampini 
1441fc17d649SStefano Zampini   /* compute initial vector in benign space if needed
144227b6a85dSStefano Zampini      and remove non-benign solution from the rhs */
144327b6a85dSStefano Zampini   benign_correction_computed = PETSC_FALSE;
144408af2428SStefano Zampini   if (rhs && pcbddc->benign_compute_correction && (pcbddc->benign_have_null || pcbddc->benign_apply_coarse_only)) {
14451f4df5f7SStefano Zampini     /* compute u^*_h using ideas similar to those in Xuemin Tu's PhD thesis (see Section 4.8.1)
14461f4df5f7SStefano Zampini        Recursively apply BDDC in the multilevel case */
14470369aaf7SStefano Zampini     if (!pcbddc->benign_vec) {
14480369aaf7SStefano Zampini       ierr = VecDuplicate(rhs,&pcbddc->benign_vec);CHKERRQ(ierr);
14490369aaf7SStefano Zampini     }
1450c69e9cc1SStefano Zampini     /* keep applying coarse solver unless we no longer have benign subdomains */
1451c69e9cc1SStefano Zampini     pcbddc->benign_apply_coarse_only = pcbddc->benign_have_null ? PETSC_TRUE : PETSC_FALSE;
145227b6a85dSStefano Zampini     if (!pcbddc->benign_skip_correction) {
14531dd7afcfSStefano Zampini       ierr = PCApply_BDDC(pc,rhs,pcbddc->benign_vec);CHKERRQ(ierr);
14543bca92a6SStefano Zampini       benign_correction_computed = PETSC_TRUE;
14551f4df5f7SStefano Zampini       if (pcbddc->temp_solution_used) {
14561f4df5f7SStefano Zampini         ierr = VecAXPY(pcbddc->temp_solution,1.0,pcbddc->benign_vec);CHKERRQ(ierr);
14571f4df5f7SStefano Zampini       }
14581f4df5f7SStefano Zampini       ierr = VecScale(pcbddc->benign_vec,-1.0);CHKERRQ(ierr);
145927b6a85dSStefano Zampini       /* store the original rhs if not done earlier */
146027b6a85dSStefano Zampini       if (save_rhs) {
146127b6a85dSStefano Zampini         ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
146292e3dcfbSStefano Zampini       }
146327b6a85dSStefano Zampini       if (pcbddc->rhs_change) {
14640369aaf7SStefano Zampini         ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,rhs,rhs);CHKERRQ(ierr);
146527b6a85dSStefano Zampini       } else {
146627b6a85dSStefano Zampini         ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,pcbddc->original_rhs,rhs);CHKERRQ(ierr);
146727b6a85dSStefano Zampini       }
14680369aaf7SStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
146927b6a85dSStefano Zampini     }
147027b6a85dSStefano Zampini     pcbddc->benign_apply_coarse_only = PETSC_FALSE;
14714df7a6bfSStefano Zampini   } else {
14724df7a6bfSStefano Zampini     ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
14730369aaf7SStefano Zampini   }
14742d4c4fecSStefano Zampini 
14752d4c4fecSStefano Zampini   /* dbg output */
1476a198735bSStefano Zampini   if (pcbddc->dbg_flag && benign_correction_computed) {
14771f4df5f7SStefano Zampini     Vec v;
1478c69e9cc1SStefano Zampini 
14791f4df5f7SStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&v);CHKERRQ(ierr);
1480c69e9cc1SStefano Zampini     if (pcbddc->ChangeOfBasisMatrix) {
14811f4df5f7SStefano Zampini       ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,v);CHKERRQ(ierr);
1482c69e9cc1SStefano Zampini     } else {
1483c69e9cc1SStefano Zampini       ierr = VecCopy(rhs,v);CHKERRQ(ierr);
1484c69e9cc1SStefano Zampini     }
14851f4df5f7SStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,v,PETSC_TRUE);CHKERRQ(ierr);
1486e0fe2d75SToby Isaac     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"LEVEL %D: is the correction benign?\n",pcbddc->current_level);CHKERRQ(ierr);
1487c69e9cc1SStefano Zampini     ierr = PetscScalarView(pcbddc->benign_n,pcbddc->benign_p0,pcbddc->dbg_viewer);CHKERRQ(ierr);
1488c69e9cc1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
14891f4df5f7SStefano Zampini     ierr = VecDestroy(&v);CHKERRQ(ierr);
14901f4df5f7SStefano Zampini   }
14910369aaf7SStefano Zampini 
14920369aaf7SStefano Zampini   /* set initial guess if using PCG */
14938ae0ca82SStefano Zampini   pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
14940369aaf7SStefano Zampini   if (x && pcbddc->use_exact_dirichlet_trick) {
14950369aaf7SStefano Zampini     ierr = VecSet(x,0.0);CHKERRQ(ierr);
14961dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
149727b6a85dSStefano Zampini       if (benign_correction_computed) { /* we have already saved the changed rhs */
14988860a134SJunchao Zhang         ierr = VecLockReadPop(pcis->vec1_global);CHKERRQ(ierr);
14991dd7afcfSStefano Zampini       } else {
15001dd7afcfSStefano Zampini         ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,pcis->vec1_global);CHKERRQ(ierr);
15011dd7afcfSStefano Zampini       }
15021dd7afcfSStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15031dd7afcfSStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15041dd7afcfSStefano Zampini     } else {
15050369aaf7SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15060369aaf7SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15071dd7afcfSStefano Zampini     }
150855c176c0SStefano Zampini     ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr);
15090369aaf7SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
151055c176c0SStefano Zampini     ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr);
1511c0decd05SBarry Smith     ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D);CHKERRQ(ierr);
15121dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
15131dd7afcfSStefano Zampini       ierr = VecSet(pcis->vec1_global,0.);CHKERRQ(ierr);
15141dd7afcfSStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15151dd7afcfSStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15161dd7afcfSStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x);CHKERRQ(ierr);
15171dd7afcfSStefano Zampini     } else {
15180369aaf7SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15190369aaf7SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15201dd7afcfSStefano Zampini     }
15210369aaf7SStefano Zampini     if (ksp) {
15220369aaf7SStefano Zampini       ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
15230369aaf7SStefano Zampini     }
15248ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_TRUE;
1525266e20e9SStefano Zampini   } else if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior && benign_correction_computed && pcbddc->use_exact_dirichlet_trick) {
15268860a134SJunchao Zhang     ierr = VecLockReadPop(pcis->vec1_global);CHKERRQ(ierr);
15270369aaf7SStefano Zampini   }
1528534831adSStefano Zampini   PetscFunctionReturn(0);
1529534831adSStefano Zampini }
1530906d46d4SStefano Zampini 
1531534831adSStefano Zampini /*
1532534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
1533534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
1534534831adSStefano Zampini 
1535534831adSStefano Zampini    Input Parameter:
1536966d8056SPierre Jolivet +  pc - the preconditioner context
1537534831adSStefano Zampini 
1538534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
1539534831adSStefano Zampini 
1540534831adSStefano Zampini    Notes:
1541534831adSStefano Zampini      The interface routine PCPostSolve() is not usually called directly by
1542534831adSStefano Zampini      the user, but instead is called by KSPSolve().
1543534831adSStefano Zampini */
1544534831adSStefano Zampini static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1545534831adSStefano Zampini {
1546534831adSStefano Zampini   PetscErrorCode ierr;
1547534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1548534831adSStefano Zampini 
1549534831adSStefano Zampini   PetscFunctionBegin;
15503972b0daSStefano Zampini   /* add solution removed in presolve */
15516bcfc461SStefano Zampini   if (x && pcbddc->rhs_change) {
155227b6a85dSStefano Zampini     if (pcbddc->temp_solution_used) {
15533425bc38SStefano Zampini       ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr);
1554af140850Sstefano_zampini     } else if (pcbddc->benign_compute_correction && pcbddc->benign_vec) {
155527b6a85dSStefano Zampini       ierr = VecAXPY(x,-1.0,pcbddc->benign_vec);CHKERRQ(ierr);
15563425bc38SStefano Zampini     }
1557af140850Sstefano_zampini     /* restore to original state (not for FETI-DP) */
1558af140850Sstefano_zampini     if (ksp) pcbddc->temp_solution_used = PETSC_FALSE;
155927b6a85dSStefano Zampini   }
156027b6a85dSStefano Zampini 
1561266e20e9SStefano Zampini   /* restore rhs to its original state (not needed for FETI-DP) */
15628d00608fSStefano Zampini   if (rhs && pcbddc->rhs_change) {
156327b6a85dSStefano Zampini     ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
15648d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_FALSE;
1565af140850Sstefano_zampini   }
15668efcfb23SStefano Zampini   /* restore ksp guess state */
15678efcfb23SStefano Zampini   if (ksp) {
15688efcfb23SStefano Zampini     ierr = KSPSetInitialGuessNonzero(ksp,pcbddc->ksp_guess_nonzero);CHKERRQ(ierr);
15698ae0ca82SStefano Zampini     /* reset flag for exact dirichlet trick */
15708ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
1571af140850Sstefano_zampini   }
1572534831adSStefano Zampini   PetscFunctionReturn(0);
1573534831adSStefano Zampini }
1574af140850Sstefano_zampini 
15750c7d97c5SJed Brown /*
15760c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
15770c7d97c5SJed Brown                   by setting data structures and options.
15780c7d97c5SJed Brown 
15790c7d97c5SJed Brown    Input Parameter:
158053cdbc3dSStefano Zampini +  pc - the preconditioner context
15810c7d97c5SJed Brown 
15820c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
15830c7d97c5SJed Brown 
15840c7d97c5SJed Brown    Notes:
15850c7d97c5SJed Brown      The interface routine PCSetUp() is not usually called directly by
15860c7d97c5SJed Brown      the user, but instead is called by PCApply() if necessary.
15870c7d97c5SJed Brown */
158853cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
15890c7d97c5SJed Brown {
15900c7d97c5SJed Brown   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1591c703fcc7SStefano Zampini   PCBDDCSubSchurs sub_schurs;
15925e8657edSStefano Zampini   Mat_IS*         matis;
159308122e43SStefano Zampini   MatNullSpace    nearnullspace;
159435509ce9Sstefano_zampini   Mat             lA;
159535509ce9Sstefano_zampini   IS              lP,zerodiag = NULL;
159691e8d312SStefano Zampini   PetscInt        nrows,ncols;
159786bfa4cfSStefano Zampini   PetscMPIInt     size;
1598c703fcc7SStefano Zampini   PetscBool       computesubschurs;
15998de1fae6SStefano Zampini   PetscBool       computeconstraintsmatrix;
16003b03f7bbSStefano Zampini   PetscBool       new_nearnullspace_provided,ismatis,rl;
1601c703fcc7SStefano Zampini   PetscErrorCode  ierr;
16020c7d97c5SJed Brown 
16030c7d97c5SJed Brown   PetscFunctionBegin;
16045e8657edSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATIS,&ismatis);CHKERRQ(ierr);
16056c4ed002SBarry Smith   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner requires matrix of type MATIS");
160691e8d312SStefano Zampini   ierr = MatGetSize(pc->pmat,&nrows,&ncols);CHKERRQ(ierr);
16076c4ed002SBarry Smith   if (nrows != ncols) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCBDDC preconditioner requires a square preconditioning matrix");
1608ffc4695bSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRMPI(ierr);
160986bfa4cfSStefano Zampini 
16105e8657edSStefano Zampini   matis = (Mat_IS*)pc->pmat->data;
1611f4ddd8eeSStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */
16123b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
161371582508SStefano Zampini      Also, BDDC builds its own KSP for the Dirichlet problem */
16143b03f7bbSStefano Zampini   rl = pcbddc->recompute_topography;
16153b03f7bbSStefano Zampini   if (!pc->setupcalled || pc->flag == DIFFERENT_NONZERO_PATTERN) rl = PETSC_TRUE;
1616820f2d46SBarry Smith   ierr = MPIU_Allreduce(&rl,&pcbddc->recompute_topography,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRMPI(ierr);
1617c83e1ba7SStefano Zampini   if (pcbddc->recompute_topography) {
1618c83e1ba7SStefano Zampini     pcbddc->graphanalyzed    = PETSC_FALSE;
1619c83e1ba7SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1620c83e1ba7SStefano Zampini   } else {
16218de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_FALSE;
1622c83e1ba7SStefano Zampini   }
1623b087196eSStefano Zampini 
1624b087196eSStefano Zampini   /* check parameters' compatibility */
1625b7ab4a40SStefano Zampini   if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE;
1626bd2a564bSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_threshold[0] != 0.0 || pcbddc->adaptive_threshold[1] != 0.0);
162786bfa4cfSStefano Zampini   pcbddc->use_deluxe_scaling   = (PetscBool)(pcbddc->use_deluxe_scaling && size > 1);
162886bfa4cfSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_selection && size > 1);
1629bf3a8328SStefano Zampini   pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined);
1630862806e4SStefano Zampini   if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE;
1631862806e4SStefano Zampini 
16325a95e1ceSStefano Zampini   computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling);
163316909a7fSStefano Zampini 
163471582508SStefano Zampini   /* activate all connected components if the netflux has been requested */
1635bb05f991SStefano Zampini   if (pcbddc->compute_nonetflux) {
1636bb05f991SStefano Zampini     pcbddc->use_vertices = PETSC_TRUE;
1637bb05f991SStefano Zampini     pcbddc->use_edges    = PETSC_TRUE;
1638bb05f991SStefano Zampini     pcbddc->use_faces    = PETSC_TRUE;
1639bb05f991SStefano Zampini   }
1640bb05f991SStefano Zampini 
1641f4ddd8eeSStefano Zampini   /* Get stdout for dbg */
164270cf5478SStefano Zampini   if (pcbddc->dbg_flag) {
164370cf5478SStefano Zampini     if (!pcbddc->dbg_viewer) {
164458a03d70SStefano Zampini       pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc));
1645f4ddd8eeSStefano Zampini     }
1646d9869140SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
164758a03d70SStefano Zampini     ierr = PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
1648f4ddd8eeSStefano Zampini   }
1649f4ddd8eeSStefano Zampini 
1650c703fcc7SStefano Zampini   /* process topology information */
165143371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_Topology[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
165271582508SStefano Zampini   if (pcbddc->recompute_topography) {
165371582508SStefano Zampini     ierr = PCBDDCComputeLocalTopologyInfo(pc);CHKERRQ(ierr);
1654c703fcc7SStefano Zampini     if (pcbddc->discretegradient) {
1655a13144ffSStefano Zampini       ierr = PCBDDCNedelecSupport(pc);CHKERRQ(ierr);
1656a13144ffSStefano Zampini     }
1657c703fcc7SStefano Zampini   }
16584f819b78SStefano Zampini   if (pcbddc->corner_selected) pcbddc->use_vertices = PETSC_TRUE;
1659a13144ffSStefano Zampini 
1660c703fcc7SStefano Zampini   /* change basis if requested by the user */
16615e8657edSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) {
16625e8657edSStefano Zampini     /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */
16635e8657edSStefano Zampini     pcbddc->use_change_of_basis = PETSC_FALSE;
16645e8657edSStefano Zampini     ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
16655e8657edSStefano Zampini   } else {
1666b96c3477SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
16675e8657edSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
16685e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
1669d16cbb6bSStefano Zampini   }
1670d16cbb6bSStefano Zampini 
16714f1b2e48SStefano Zampini   /*
1672c703fcc7SStefano Zampini      Compute change of basis on local pressures (aka zerodiag dofs) with the benign trick
16734f1b2e48SStefano Zampini      This should come earlier then PCISSetUp for extracting the correct subdomain matrices
16744f1b2e48SStefano Zampini   */
16751dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
1676d16cbb6bSStefano Zampini   if (pcbddc->benign_saddle_point) {
16779f47a83aSStefano Zampini     PC_IS* pcis = (PC_IS*)pc->data;
16789f47a83aSStefano Zampini 
167905b28244SStefano Zampini     if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE;
16803b03f7bbSStefano Zampini     /* detect local saddle point and change the basis in pcbddc->local_mat */
16813b03f7bbSStefano Zampini     ierr = PCBDDCBenignDetectSaddlePoint(pc,(PetscBool)(!pcbddc->recompute_topography),&zerodiag);CHKERRQ(ierr);
1682a3df083aSStefano Zampini     /* pop B0 mat from local mat */
1683c263805aSStefano Zampini     ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
16841dd7afcfSStefano Zampini     /* give pcis a hint to not reuse submatrices during PCISCreate */
16851dd7afcfSStefano Zampini     if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) {
16861dd7afcfSStefano Zampini       if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) {
16871dd7afcfSStefano Zampini         pcis->reusesubmatrices = PETSC_FALSE;
16881dd7afcfSStefano Zampini       } else {
1689a3df083aSStefano Zampini         pcis->reusesubmatrices = PETSC_TRUE;
16901dd7afcfSStefano Zampini       }
1691a3df083aSStefano Zampini     } else {
16929f47a83aSStefano Zampini       pcis->reusesubmatrices = PETSC_FALSE;
1693674ae819SStefano Zampini     }
1694a3df083aSStefano Zampini   }
169527b6a85dSStefano Zampini 
16968037d520SStefano Zampini   /* propagate relevant information */
169706a4e24aSStefano Zampini   if (matis->A->symmetric_set) {
169806a4e24aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
169906a4e24aSStefano Zampini   }
170006a4e24aSStefano Zampini   if (matis->A->spd_set) {
170106a4e24aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SPD,matis->A->spd);CHKERRQ(ierr);
170206a4e24aSStefano Zampini   }
1703e496cd5dSStefano Zampini 
17045e8657edSStefano Zampini   /* Set up all the "iterative substructuring" common block without computing solvers */
17055e8657edSStefano Zampini   {
17065e8657edSStefano Zampini     Mat temp_mat;
17075e8657edSStefano Zampini 
17085e8657edSStefano Zampini     temp_mat = matis->A;
17095e8657edSStefano Zampini     matis->A = pcbddc->local_mat;
1710d9869140SStefano Zampini     ierr = PCISSetUp(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
17115e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
17125e8657edSStefano Zampini     matis->A = temp_mat;
17135e8657edSStefano Zampini   }
1714684f6988SStefano Zampini 
171581d14e9dSStefano Zampini   /* Analyze interface */
171664ac59b8SStefano Zampini   if (!pcbddc->graphanalyzed) {
1717674ae819SStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
17188de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1719345ecf6cSStefano Zampini     if (pcbddc->adaptive_selection && !pcbddc->use_deluxe_scaling && !pcbddc->mat_graph->twodim) {
17204247aa23Sstefano_zampini       SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot compute the adaptive primal space for a problem with 3D edges without deluxe scaling");
1721345ecf6cSStefano Zampini     }
1722a198735bSStefano Zampini     if (pcbddc->compute_nonetflux) {
1723669cc0f4SStefano Zampini       MatNullSpace nnfnnsp;
1724669cc0f4SStefano Zampini 
172521ef3d20SStefano Zampini       if (!pcbddc->divudotp) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Missing divudotp operator");
17268ae0ca82SStefano Zampini       ierr = PCBDDCComputeNoNetFlux(pc->pmat,pcbddc->divudotp,pcbddc->divudotp_trans,pcbddc->divudotp_vl2l,pcbddc->mat_graph,&nnfnnsp);CHKERRQ(ierr);
172771582508SStefano Zampini       /* TODO what if a nearnullspace is already attached? */
17288037d520SStefano Zampini       if (nnfnnsp) {
1729669cc0f4SStefano Zampini         ierr = MatSetNearNullSpace(pc->pmat,nnfnnsp);CHKERRQ(ierr);
1730669cc0f4SStefano Zampini         ierr = MatNullSpaceDestroy(&nnfnnsp);CHKERRQ(ierr);
1731669cc0f4SStefano Zampini       }
1732674ae819SStefano Zampini     }
17338037d520SStefano Zampini   }
173443371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_Topology[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
1735fb8d54d4SStefano Zampini 
17365408967cSStefano Zampini   /* check existence of a divergence free extension, i.e.
17375408967cSStefano Zampini      b(v_I,p_0) = 0 for all v_I (raise error if not).
17385408967cSStefano Zampini      Also, check that PCBDDCBenignGetOrSetP0 works */
1739ff1f7e73Sstefano_zampini   if (pcbddc->benign_saddle_point && pcbddc->dbg_flag > 1) {
17405408967cSStefano Zampini     ierr = PCBDDCBenignCheck(pc,zerodiag);CHKERRQ(ierr);
174109f581a4SStefano Zampini   }
17424f1b2e48SStefano Zampini   ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
174306f24817SStefano Zampini 
1744b96c3477SStefano Zampini   /* Setup local dirichlet solver ksp_D and sub_schurs solvers */
1745c703fcc7SStefano Zampini   if (computesubschurs && pcbddc->recompute_topography) {
174608122e43SStefano Zampini     ierr = PCBDDCInitSubSchurs(pc);CHKERRQ(ierr);
1747b1b3d7a2SStefano Zampini   }
17489d54b7f4SStefano Zampini   /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/
17499d54b7f4SStefano Zampini   if (!pcbddc->use_deluxe_scaling) {
17509d54b7f4SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
17519d54b7f4SStefano Zampini   }
1752c703fcc7SStefano Zampini 
1753c703fcc7SStefano Zampini   /* finish setup solvers and do adaptive selection of constraints */
1754b334f244SStefano Zampini   sub_schurs = pcbddc->sub_schurs;
1755b334f244SStefano Zampini   if (sub_schurs && sub_schurs->schur_explicit) {
17562070dbb6SStefano Zampini     if (computesubschurs) {
175708122e43SStefano Zampini       ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
17582070dbb6SStefano Zampini     }
1759d5574798SStefano Zampini     ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
1760d5574798SStefano Zampini   } else {
1761d5574798SStefano Zampini     ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
17622070dbb6SStefano Zampini     if (computesubschurs) {
1763d5574798SStefano Zampini       ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
1764d5574798SStefano Zampini     }
17652070dbb6SStefano Zampini   }
176608122e43SStefano Zampini   if (pcbddc->adaptive_selection) {
176708122e43SStefano Zampini     ierr = PCBDDCAdaptiveSelection(pc);CHKERRQ(ierr);
17688de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1769b7eb3628SStefano Zampini   }
1770684f6988SStefano Zampini 
1771f4ddd8eeSStefano Zampini   /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */
1772fb8d54d4SStefano Zampini   new_nearnullspace_provided = PETSC_FALSE;
1773f4ddd8eeSStefano Zampini   ierr = MatGetNearNullSpace(pc->pmat,&nearnullspace);CHKERRQ(ierr);
1774f4ddd8eeSStefano Zampini   if (pcbddc->onearnullspace) { /* already used nearnullspace */
1775f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* near null space attached to mat has been destroyed */
1776f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1777f4ddd8eeSStefano Zampini     } else {
1778f4ddd8eeSStefano Zampini       /* determine if the two nullspaces are different (should be lightweight) */
1779f4ddd8eeSStefano Zampini       if (nearnullspace != pcbddc->onearnullspace) {
1780f4ddd8eeSStefano Zampini         new_nearnullspace_provided = PETSC_TRUE;
1781165b64e2SStefano Zampini       } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */
1782f4ddd8eeSStefano Zampini         PetscInt         i;
1783165b64e2SStefano Zampini         const Vec        *nearnullvecs;
1784165b64e2SStefano Zampini         PetscObjectState state;
1785165b64e2SStefano Zampini         PetscInt         nnsp_size;
1786165b64e2SStefano Zampini         ierr = MatNullSpaceGetVecs(nearnullspace,NULL,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
1787f4ddd8eeSStefano Zampini         for (i=0;i<nnsp_size;i++) {
1788f4ddd8eeSStefano Zampini           ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&state);CHKERRQ(ierr);
1789165b64e2SStefano Zampini           if (pcbddc->onearnullvecs_state[i] != state) {
1790f4ddd8eeSStefano Zampini             new_nearnullspace_provided = PETSC_TRUE;
1791f4ddd8eeSStefano Zampini             break;
1792f4ddd8eeSStefano Zampini           }
1793f4ddd8eeSStefano Zampini         }
1794f4ddd8eeSStefano Zampini       }
1795f4ddd8eeSStefano Zampini     }
1796f4ddd8eeSStefano Zampini   } else {
1797f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* both nearnullspaces are null */
1798f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_FALSE;
1799f4ddd8eeSStefano Zampini     } else { /* nearnullspace attached later */
1800f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1801f4ddd8eeSStefano Zampini     }
1802f4ddd8eeSStefano Zampini   }
1803f4ddd8eeSStefano Zampini 
1804f4ddd8eeSStefano Zampini   /* Setup constraints and related work vectors */
1805727cdba6SStefano Zampini   /* reset primal space flags */
180643371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_LocalWork[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
1807f4ddd8eeSStefano Zampini   pcbddc->new_primal_space = PETSC_FALSE;
1808727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_FALSE;
18098de1fae6SStefano Zampini   if (computeconstraintsmatrix || new_nearnullspace_provided) {
1810727cdba6SStefano Zampini     /* It also sets the primal space flags */
1811674ae819SStefano Zampini     ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr);
18129543d0ffSStefano Zampini   }
1813e7b262bdSStefano Zampini   /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */
1814f4ddd8eeSStefano Zampini   ierr = PCBDDCSetUpLocalWorkVectors(pc);CHKERRQ(ierr);
18155e8657edSStefano Zampini 
18165e8657edSStefano Zampini   if (pcbddc->use_change_of_basis) {
18175e8657edSStefano Zampini     PC_IS *pcis = (PC_IS*)(pc->data);
18185e8657edSStefano Zampini 
18195e8657edSStefano Zampini     ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
18204f1b2e48SStefano Zampini     if (pcbddc->benign_change) {
18211dd7afcfSStefano Zampini       ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
1822c263805aSStefano Zampini       /* pop B0 from pcbddc->local_mat */
1823c263805aSStefano Zampini       ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
1824c263805aSStefano Zampini     }
18255e8657edSStefano Zampini     /* get submatrices */
18265e8657edSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
18275e8657edSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
18285e8657edSStefano Zampini     ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);
18297dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB);CHKERRQ(ierr);
18307dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr);
18317dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr);
18323975b054SStefano Zampini     /* set flag in pcis to not reuse submatrices during PCISCreate */
18333975b054SStefano Zampini     pcis->reusesubmatrices = PETSC_FALSE;
18349c6a02ceSStefano Zampini   } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) {
1835b96c3477SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
18365e8657edSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
18375e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
18385e8657edSStefano Zampini   }
183935509ce9Sstefano_zampini 
184035509ce9Sstefano_zampini   /* interface pressure block row for B_C */
184135509ce9Sstefano_zampini   ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP" ,(PetscObject*)&lP);CHKERRQ(ierr);
184235509ce9Sstefano_zampini   ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA);CHKERRQ(ierr);
184335509ce9Sstefano_zampini   if (lA && lP) {
184435509ce9Sstefano_zampini     PC_IS*    pcis = (PC_IS*)pc->data;
184535509ce9Sstefano_zampini     Mat       B_BI,B_BB,Bt_BI,Bt_BB;
184635509ce9Sstefano_zampini     PetscBool issym;
184735509ce9Sstefano_zampini     ierr = MatIsSymmetric(lA,PETSC_SMALL,&issym);CHKERRQ(ierr);
18486cc1294bSstefano_zampini     if (issym) {
18497dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI);CHKERRQ(ierr);
18507dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB);CHKERRQ(ierr);
185135509ce9Sstefano_zampini       ierr = MatCreateTranspose(B_BI,&Bt_BI);CHKERRQ(ierr);
185235509ce9Sstefano_zampini       ierr = MatCreateTranspose(B_BB,&Bt_BB);CHKERRQ(ierr);
185335509ce9Sstefano_zampini     } else {
18547dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI);CHKERRQ(ierr);
18557dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB);CHKERRQ(ierr);
18567dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,pcis->is_I_local,lP,MAT_INITIAL_MATRIX,&Bt_BI);CHKERRQ(ierr);
18577dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,pcis->is_B_local,lP,MAT_INITIAL_MATRIX,&Bt_BB);CHKERRQ(ierr);
185835509ce9Sstefano_zampini     }
185935509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BI",(PetscObject)B_BI);CHKERRQ(ierr);
186035509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BB",(PetscObject)B_BB);CHKERRQ(ierr);
186135509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BI",(PetscObject)Bt_BI);CHKERRQ(ierr);
186235509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BB",(PetscObject)Bt_BB);CHKERRQ(ierr);
186335509ce9Sstefano_zampini     ierr = MatDestroy(&B_BI);CHKERRQ(ierr);
186435509ce9Sstefano_zampini     ierr = MatDestroy(&B_BB);CHKERRQ(ierr);
186535509ce9Sstefano_zampini     ierr = MatDestroy(&Bt_BI);CHKERRQ(ierr);
186635509ce9Sstefano_zampini     ierr = MatDestroy(&Bt_BB);CHKERRQ(ierr);
186735509ce9Sstefano_zampini   }
186843371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_LocalWork[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
186935509ce9Sstefano_zampini 
1870b96c3477SStefano Zampini   /* SetUp coarse and local Neumann solvers */
187199cc7994SStefano Zampini   ierr = PCBDDCSetUpSolvers(pc);CHKERRQ(ierr);
1872b96c3477SStefano Zampini   /* SetUp Scaling operator */
18739d54b7f4SStefano Zampini   if (pcbddc->use_deluxe_scaling) {
1874674ae819SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
18750c7d97c5SJed Brown   }
1876c703fcc7SStefano Zampini 
18771dd7afcfSStefano Zampini   /* mark topography as done */
187856282151SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
18790369aaf7SStefano Zampini 
18801dd7afcfSStefano Zampini   /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */
18811dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_FALSE);CHKERRQ(ierr);
18821dd7afcfSStefano Zampini 
188358a03d70SStefano Zampini   if (pcbddc->dbg_flag) {
188458a03d70SStefano Zampini     ierr = PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
1885d9869140SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
18862b510759SStefano Zampini   }
18870c7d97c5SJed Brown   PetscFunctionReturn(0);
18880c7d97c5SJed Brown }
18890c7d97c5SJed Brown 
18900c7d97c5SJed Brown /*
189150efa1b5SStefano Zampini    PCApply_BDDC - Applies the BDDC operator to a vector.
18920c7d97c5SJed Brown 
18930c7d97c5SJed Brown    Input Parameters:
18940f202f7eSStefano Zampini +  pc - the preconditioner context
18950f202f7eSStefano Zampini -  r - input vector (global)
18960c7d97c5SJed Brown 
18970c7d97c5SJed Brown    Output Parameter:
18980c7d97c5SJed Brown .  z - output vector (global)
18990c7d97c5SJed Brown 
19000c7d97c5SJed Brown    Application Interface Routine: PCApply()
19010c7d97c5SJed Brown  */
190253cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
19030c7d97c5SJed Brown {
19040c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
19050c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1906b3338236SStefano Zampini   Mat               lA = NULL;
1907b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
19080c7d97c5SJed Brown   PetscErrorCode    ierr;
19093b03a366Sstefano_zampini   const PetscScalar one = 1.0;
19103b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
19112617d88aSStefano Zampini   const PetscScalar zero = 0.0;
19120c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
19130c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
1914b097fa66SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */
19150c7d97c5SJed Brown 
19160c7d97c5SJed Brown   PetscFunctionBegin;
1917f3d41395Sstefano_zampini   ierr = PetscCitationsRegister(citation,&cited);CHKERRQ(ierr);
1918b3338236SStefano Zampini   if (pcbddc->switch_static) {
1919b3338236SStefano Zampini     ierr = MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat,&lA);CHKERRQ(ierr);
1920b3338236SStefano Zampini   }
1921b3338236SStefano Zampini 
19221dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
19231dd7afcfSStefano Zampini     Vec swap;
192427b6a85dSStefano Zampini 
192527b6a85dSStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
19261dd7afcfSStefano Zampini     swap = pcbddc->work_change;
19271dd7afcfSStefano Zampini     pcbddc->work_change = r;
19281dd7afcfSStefano Zampini     r = swap;
19291dd7afcfSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
19309cc2a9b1Sstefano_zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) {
19311dd7afcfSStefano Zampini       ierr = VecCopy(r,pcis->vec1_global);CHKERRQ(ierr);
19328860a134SJunchao Zhang       ierr = VecLockReadPush(pcis->vec1_global);CHKERRQ(ierr);
19331dd7afcfSStefano Zampini     }
19341dd7afcfSStefano Zampini   }
193527b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
1936015636ebSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
1937efc2fbd9SStefano Zampini   }
1938bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_DIRICHLET && !pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1939b097fa66SStefano Zampini     ierr = VecCopy(r,z);CHKERRQ(ierr);
19400c7d97c5SJed Brown     /* First Dirichlet solve */
19410c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19420c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19430c7d97c5SJed Brown     /*
19440c7d97c5SJed Brown       Assembling right hand side for BDDC operator
1945b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
1946674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
19470c7d97c5SJed Brown     */
1948b097fa66SStefano Zampini     if (n_D) {
194955c176c0SStefano Zampini       ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr);
1950b097fa66SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
195155c176c0SStefano Zampini       ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr);
1952c0decd05SBarry Smith       ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D);CHKERRQ(ierr);
19530c7d97c5SJed Brown       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
195416909a7fSStefano Zampini       if (pcbddc->switch_static) {
195516909a7fSStefano Zampini         ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
195616909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
195716909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
195816909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
1959b3338236SStefano Zampini           ierr = MatMult(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
196016909a7fSStefano Zampini         } else {
196116909a7fSStefano Zampini           ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1962b3338236SStefano Zampini           ierr = MatMult(lA,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
196316909a7fSStefano Zampini           ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
196416909a7fSStefano Zampini         }
196516909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
196616909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
196716909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
196816909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
196916909a7fSStefano Zampini       } else {
1970b097fa66SStefano Zampini         ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
197116909a7fSStefano Zampini       }
1972b097fa66SStefano Zampini     } else {
1973b097fa66SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1974b097fa66SStefano Zampini     }
19750c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
19760c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1977674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
1978b76ba322SStefano Zampini   } else {
19794fee134fSStefano Zampini     if (!pcbddc->benign_apply_coarse_only) {
1980674ae819SStefano Zampini       ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
1981b76ba322SStefano Zampini     }
19824fee134fSStefano Zampini   }
1983bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) {
1984bc960bbfSJed Brown     if (!pcbddc->switch_static) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"You forgot to pass -pc_bddc_switch_static");
1985bc960bbfSJed Brown     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1986bc960bbfSJed Brown     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1987bc960bbfSJed Brown   }
1988b76ba322SStefano Zampini 
19892617d88aSStefano Zampini   /* Apply interface preconditioner
19902617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
1991dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
19922617d88aSStefano Zampini 
1993674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
1994674ae819SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
1995bc960bbfSJed Brown   if (pcbddc->interface_extension == PC_BDDC_INTERFACE_EXT_LUMP) {
1996bc960bbfSJed Brown     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1997bc960bbfSJed Brown     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec1_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1998bc960bbfSJed Brown     PetscFunctionReturn(0);
1999bc960bbfSJed Brown   }
20003b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
20010c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
20020c7d97c5SJed Brown   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2003b097fa66SStefano Zampini   if (n_B) {
200416909a7fSStefano Zampini     if (pcbddc->switch_static) {
200516909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
200616909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
200716909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
200816909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
200916909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
2010b3338236SStefano Zampini         ierr = MatMult(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
201116909a7fSStefano Zampini       } else {
201216909a7fSStefano Zampini         ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
2013b3338236SStefano Zampini         ierr = MatMult(lA,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
201416909a7fSStefano Zampini         ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
201516909a7fSStefano Zampini       }
201616909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
201716909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
201816909a7fSStefano Zampini     } else {
20190c7d97c5SJed Brown       ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
202016909a7fSStefano Zampini     }
202116909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
202216909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
2023b3338236SStefano Zampini       ierr = MatMult(lA,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
202416909a7fSStefano Zampini     } else {
202516909a7fSStefano Zampini       ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N);CHKERRQ(ierr);
2026b3338236SStefano Zampini       ierr = MatMult(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
202716909a7fSStefano Zampini       ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D);CHKERRQ(ierr);
202816909a7fSStefano Zampini     }
2029b097fa66SStefano Zampini   }
203055c176c0SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr);
2031df187020SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
203255c176c0SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr);
2033c0decd05SBarry Smith   ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec4_D);CHKERRQ(ierr);
2034efc2fbd9SStefano Zampini 
20358ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
2036b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2037b097fa66SStefano Zampini       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
2038b097fa66SStefano Zampini     } else {
2039b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
2040b097fa66SStefano Zampini     }
20410c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20420c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2043b097fa66SStefano Zampini   } else {
2044b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2045b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
2046b097fa66SStefano Zampini     } else {
2047b097fa66SStefano Zampini       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
2048b097fa66SStefano Zampini     }
2049b097fa66SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2050b097fa66SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2051b097fa66SStefano Zampini   }
205227b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
20531dd7afcfSStefano Zampini     if (pcbddc->benign_apply_coarse_only) {
2054580bdb30SBarry Smith       ierr = PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n);CHKERRQ(ierr);
20551dd7afcfSStefano Zampini     }
2056015636ebSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
2057efc2fbd9SStefano Zampini   }
20581f4df5f7SStefano Zampini 
20591dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2060f913dca9SStefano Zampini     pcbddc->work_change = r;
20611dd7afcfSStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
20621dd7afcfSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
20631dd7afcfSStefano Zampini   }
20640c7d97c5SJed Brown   PetscFunctionReturn(0);
20650c7d97c5SJed Brown }
206650efa1b5SStefano Zampini 
206750efa1b5SStefano Zampini /*
206850efa1b5SStefano Zampini    PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector.
206950efa1b5SStefano Zampini 
207050efa1b5SStefano Zampini    Input Parameters:
20710f202f7eSStefano Zampini +  pc - the preconditioner context
20720f202f7eSStefano Zampini -  r - input vector (global)
207350efa1b5SStefano Zampini 
207450efa1b5SStefano Zampini    Output Parameter:
207550efa1b5SStefano Zampini .  z - output vector (global)
207650efa1b5SStefano Zampini 
207750efa1b5SStefano Zampini    Application Interface Routine: PCApplyTranspose()
207850efa1b5SStefano Zampini  */
207950efa1b5SStefano Zampini PetscErrorCode PCApplyTranspose_BDDC(PC pc,Vec r,Vec z)
208050efa1b5SStefano Zampini {
208150efa1b5SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
208250efa1b5SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
2083b3338236SStefano Zampini   Mat               lA = NULL;
2084b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
208550efa1b5SStefano Zampini   PetscErrorCode    ierr;
208650efa1b5SStefano Zampini   const PetscScalar one = 1.0;
208750efa1b5SStefano Zampini   const PetscScalar m_one = -1.0;
208850efa1b5SStefano Zampini   const PetscScalar zero = 0.0;
208950efa1b5SStefano Zampini 
209050efa1b5SStefano Zampini   PetscFunctionBegin;
2091f3d41395Sstefano_zampini   ierr = PetscCitationsRegister(citation,&cited);CHKERRQ(ierr);
2092b3338236SStefano Zampini   if (pcbddc->switch_static) {
2093b3338236SStefano Zampini     ierr = MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat,&lA);CHKERRQ(ierr);
2094b3338236SStefano Zampini   }
20951dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
20961dd7afcfSStefano Zampini     Vec swap;
209727b6a85dSStefano Zampini 
209827b6a85dSStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
20991dd7afcfSStefano Zampini     swap = pcbddc->work_change;
21001dd7afcfSStefano Zampini     pcbddc->work_change = r;
21011dd7afcfSStefano Zampini     r = swap;
210227b6a85dSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
21038ae0ca82SStefano Zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->exact_dirichlet_trick_app && pcbddc->change_interior) {
210427b6a85dSStefano Zampini       ierr = VecCopy(r,pcis->vec1_global);CHKERRQ(ierr);
21058860a134SJunchao Zhang       ierr = VecLockReadPush(pcis->vec1_global);CHKERRQ(ierr);
21061dd7afcfSStefano Zampini     }
210727b6a85dSStefano Zampini   }
210827b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
2109537c1cdfSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
2110537c1cdfSStefano Zampini   }
21118ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
2112b097fa66SStefano Zampini     ierr = VecCopy(r,z);CHKERRQ(ierr);
211350efa1b5SStefano Zampini     /* First Dirichlet solve */
211450efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
211550efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
211650efa1b5SStefano Zampini     /*
211750efa1b5SStefano Zampini       Assembling right hand side for BDDC operator
2118b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
211950efa1b5SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
212050efa1b5SStefano Zampini     */
2121b097fa66SStefano Zampini     if (n_D) {
212255c176c0SStefano Zampini       ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr);
2123b097fa66SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
212455c176c0SStefano Zampini       ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr);
2125c0decd05SBarry Smith       ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D);CHKERRQ(ierr);
212650efa1b5SStefano Zampini       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
212716909a7fSStefano Zampini       if (pcbddc->switch_static) {
212816909a7fSStefano Zampini         ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
212916909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
213016909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
213116909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
2132b3338236SStefano Zampini           ierr = MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
213316909a7fSStefano Zampini         } else {
213416909a7fSStefano Zampini           ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
2135b3338236SStefano Zampini           ierr = MatMultTranspose(lA,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
213616909a7fSStefano Zampini           ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
213716909a7fSStefano Zampini         }
213816909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
213916909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
214016909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
214116909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
214216909a7fSStefano Zampini       } else {
2143b097fa66SStefano Zampini         ierr = MatMultTranspose(pcis->A_IB,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
214416909a7fSStefano Zampini       }
2145b097fa66SStefano Zampini     } else {
2146b097fa66SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
2147b097fa66SStefano Zampini     }
214850efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
214950efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
215050efa1b5SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
215150efa1b5SStefano Zampini   } else {
215250efa1b5SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
215350efa1b5SStefano Zampini   }
215450efa1b5SStefano Zampini 
215550efa1b5SStefano Zampini   /* Apply interface preconditioner
215650efa1b5SStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
2157dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_TRUE);CHKERRQ(ierr);
215850efa1b5SStefano Zampini 
215950efa1b5SStefano Zampini   /* Apply transpose of partition of unity operator */
216050efa1b5SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
216150efa1b5SStefano Zampini 
216250efa1b5SStefano Zampini   /* Second Dirichlet solve and assembling of output */
216350efa1b5SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
216450efa1b5SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2165b097fa66SStefano Zampini   if (n_B) {
216616909a7fSStefano Zampini     if (pcbddc->switch_static) {
216716909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
216816909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
216916909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
217016909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
217116909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
2172b3338236SStefano Zampini         ierr = MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
217316909a7fSStefano Zampini       } else {
217416909a7fSStefano Zampini         ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
2175b3338236SStefano Zampini         ierr = MatMultTranspose(lA,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
217616909a7fSStefano Zampini         ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
217716909a7fSStefano Zampini       }
217816909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
217916909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
218016909a7fSStefano Zampini     } else {
218150efa1b5SStefano Zampini       ierr = MatMultTranspose(pcis->A_BI,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
218216909a7fSStefano Zampini     }
218316909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
218416909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
2185b3338236SStefano Zampini       ierr = MatMultTranspose(lA,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
218616909a7fSStefano Zampini     } else {
218716909a7fSStefano Zampini       ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N);CHKERRQ(ierr);
2188b3338236SStefano Zampini       ierr = MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
218916909a7fSStefano Zampini       ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D);CHKERRQ(ierr);
219016909a7fSStefano Zampini     }
2191b097fa66SStefano Zampini   }
219255c176c0SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr);
2193b0147a47SStefano Zampini   ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
219455c176c0SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],pc,0,0,0);CHKERRQ(ierr);
2195c0decd05SBarry Smith   ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec4_D);CHKERRQ(ierr);
21968ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
2197b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2198b097fa66SStefano Zampini       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
2199b097fa66SStefano Zampini     } else {
2200b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
2201b097fa66SStefano Zampini     }
220250efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
220350efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2204b097fa66SStefano Zampini   } else {
2205b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2206b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
2207b097fa66SStefano Zampini     } else {
2208b097fa66SStefano Zampini       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
2209b097fa66SStefano Zampini     }
2210b097fa66SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2211b097fa66SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2212b097fa66SStefano Zampini   }
221327b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
2214537c1cdfSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
2215537c1cdfSStefano Zampini   }
22161dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2217f913dca9SStefano Zampini     pcbddc->work_change = r;
22181dd7afcfSStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
22191dd7afcfSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
22201dd7afcfSStefano Zampini   }
222150efa1b5SStefano Zampini   PetscFunctionReturn(0);
222250efa1b5SStefano Zampini }
2223674ae819SStefano Zampini 
22249326c5c6Sstefano_zampini PetscErrorCode PCReset_BDDC(PC pc)
2225da1bb401SStefano Zampini {
2226da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
22279326c5c6Sstefano_zampini   PC_IS          *pcis = (PC_IS*)pc->data;
22289326c5c6Sstefano_zampini   KSP            kspD,kspR,kspC;
2229da1bb401SStefano Zampini   PetscErrorCode ierr;
2230da1bb401SStefano Zampini 
2231da1bb401SStefano Zampini   PetscFunctionBegin;
2232674ae819SStefano Zampini   /* free BDDC custom data  */
2233674ae819SStefano Zampini   ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr);
2234674ae819SStefano Zampini   /* destroy objects related to topography */
2235674ae819SStefano Zampini   ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
223634a97f8cSStefano Zampini   /* destroy objects for scaling operator */
2237674ae819SStefano Zampini   ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
2238674ae819SStefano Zampini   /* free solvers stuff */
2239674ae819SStefano Zampini   ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
224062a6ff1dSStefano Zampini   /* free global vectors needed in presolve */
224162a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr);
224262a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr);
22431dd7afcfSStefano Zampini   /* free data created by PCIS */
22441dd7afcfSStefano Zampini   ierr = PCISDestroy(pc);CHKERRQ(ierr);
22459326c5c6Sstefano_zampini 
22469326c5c6Sstefano_zampini   /* restore defaults */
22479326c5c6Sstefano_zampini   kspD = pcbddc->ksp_D;
22489326c5c6Sstefano_zampini   kspR = pcbddc->ksp_R;
22499326c5c6Sstefano_zampini   kspC = pcbddc->coarse_ksp;
22509326c5c6Sstefano_zampini   ierr = PetscMemzero(pc->data,sizeof(*pcbddc));CHKERRQ(ierr);
22519326c5c6Sstefano_zampini   pcis->n_neigh                     = -1;
22529326c5c6Sstefano_zampini   pcis->scaling_factor              = 1.0;
22539326c5c6Sstefano_zampini   pcis->reusesubmatrices            = PETSC_TRUE;
22549326c5c6Sstefano_zampini   pcbddc->use_local_adj             = PETSC_TRUE;
22559326c5c6Sstefano_zampini   pcbddc->use_vertices              = PETSC_TRUE;
22569326c5c6Sstefano_zampini   pcbddc->use_edges                 = PETSC_TRUE;
22579326c5c6Sstefano_zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
22589326c5c6Sstefano_zampini   pcbddc->vertex_size               = 1;
22599326c5c6Sstefano_zampini   pcbddc->recompute_topography      = PETSC_TRUE;
22609326c5c6Sstefano_zampini   pcbddc->coarse_size               = -1;
22619326c5c6Sstefano_zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
22629326c5c6Sstefano_zampini   pcbddc->coarsening_ratio          = 8;
22639326c5c6Sstefano_zampini   pcbddc->coarse_eqs_per_proc       = 1;
22649326c5c6Sstefano_zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
22659326c5c6Sstefano_zampini   pcbddc->nedfield                  = -1;
22669326c5c6Sstefano_zampini   pcbddc->nedglobal                 = PETSC_TRUE;
22679326c5c6Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
22689326c5c6Sstefano_zampini   pcbddc->sub_schurs_layers         = -1;
22699326c5c6Sstefano_zampini   pcbddc->ksp_D                     = kspD;
22709326c5c6Sstefano_zampini   pcbddc->ksp_R                     = kspR;
22719326c5c6Sstefano_zampini   pcbddc->coarse_ksp                = kspC;
22729326c5c6Sstefano_zampini   PetscFunctionReturn(0);
22739326c5c6Sstefano_zampini }
22749326c5c6Sstefano_zampini 
22759326c5c6Sstefano_zampini PetscErrorCode PCDestroy_BDDC(PC pc)
22769326c5c6Sstefano_zampini {
22779326c5c6Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
22789326c5c6Sstefano_zampini   PetscErrorCode ierr;
22799326c5c6Sstefano_zampini 
22809326c5c6Sstefano_zampini   PetscFunctionBegin;
22819326c5c6Sstefano_zampini   ierr = PCReset_BDDC(pc);CHKERRQ(ierr);
22829326c5c6Sstefano_zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
22839326c5c6Sstefano_zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
22849326c5c6Sstefano_zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
2285a13144ffSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",NULL);CHKERRQ(ierr);
2286a198735bSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",NULL);CHKERRQ(ierr);
2287906d46d4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",NULL);CHKERRQ(ierr);
2288674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr);
228930368db7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",NULL);CHKERRQ(ierr);
2290bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr);
22912b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL);CHKERRQ(ierr);
2292b8ffe317SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL);CHKERRQ(ierr);
22932b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL);CHKERRQ(ierr);
2294bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
229582ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
2296bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
229782ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
2298bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
229982ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
2300bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
2301785d1243SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
2302bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr);
230363602bcaSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",NULL);CHKERRQ(ierr);
2304bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr);
2305bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr);
2306bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr);
2307bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr);
2308a06fd7f2SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",NULL);CHKERRQ(ierr);
2309ab8c8b98SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",NULL);CHKERRQ(ierr);
2310674ae819SStefano Zampini   ierr = PetscFree(pc->data);CHKERRQ(ierr);
2311da1bb401SStefano Zampini   PetscFunctionReturn(0);
2312da1bb401SStefano Zampini }
23131e6b0712SBarry Smith 
2314ab8c8b98SStefano Zampini static PetscErrorCode PCSetCoordinates_BDDC(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
2315ab8c8b98SStefano Zampini {
2316ab8c8b98SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2317ab8c8b98SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
2318ab8c8b98SStefano Zampini   PetscErrorCode ierr;
2319ab8c8b98SStefano Zampini 
2320ab8c8b98SStefano Zampini   PetscFunctionBegin;
2321ab8c8b98SStefano Zampini   ierr = PetscFree(mat_graph->coords);CHKERRQ(ierr);
2322ab8c8b98SStefano Zampini   ierr = PetscMalloc1(nloc*dim,&mat_graph->coords);CHKERRQ(ierr);
2323580bdb30SBarry Smith   ierr = PetscArraycpy(mat_graph->coords,coords,nloc*dim);CHKERRQ(ierr);
2324ab8c8b98SStefano Zampini   mat_graph->cnloc = nloc;
2325ab8c8b98SStefano Zampini   mat_graph->cdim  = dim;
2326ab8c8b98SStefano Zampini   mat_graph->cloc  = PETSC_FALSE;
23274f819b78SStefano Zampini   /* flg setup */
23284f819b78SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
23294f819b78SStefano Zampini   pcbddc->corner_selected = PETSC_FALSE;
2330ab8c8b98SStefano Zampini   PetscFunctionReturn(0);
2331ab8c8b98SStefano Zampini }
2332ab8c8b98SStefano Zampini 
2333a06fd7f2SStefano Zampini static PetscErrorCode PCPreSolveChangeRHS_BDDC(PC pc, PetscBool* change)
2334a06fd7f2SStefano Zampini {
2335a06fd7f2SStefano Zampini   PetscFunctionBegin;
2336a06fd7f2SStefano Zampini   *change = PETSC_TRUE;
2337a06fd7f2SStefano Zampini   PetscFunctionReturn(0);
2338a06fd7f2SStefano Zampini }
2339a06fd7f2SStefano Zampini 
23403425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
23413425bc38SStefano Zampini {
2342674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
2343266e20e9SStefano Zampini   Vec            work;
23443425bc38SStefano Zampini   PC_IS*         pcis;
23453425bc38SStefano Zampini   PC_BDDC*       pcbddc;
23463425bc38SStefano Zampini   PetscErrorCode ierr;
23470c7d97c5SJed Brown 
23483425bc38SStefano Zampini   PetscFunctionBegin;
23493425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
23503425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
23513425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
23523425bc38SStefano Zampini 
2353229984c5Sstefano_zampini   ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr);
2354229984c5Sstefano_zampini   /* copy rhs since we may change it during PCPreSolve_BDDC */
2355229984c5Sstefano_zampini   if (!pcbddc->original_rhs) {
2356229984c5Sstefano_zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
2357229984c5Sstefano_zampini   }
23586cc1294bSstefano_zampini   if (mat_ctx->rhs_flip) {
23596cc1294bSstefano_zampini     ierr = VecPointwiseMult(pcbddc->original_rhs,standard_rhs,mat_ctx->rhs_flip);CHKERRQ(ierr);
23606cc1294bSstefano_zampini   } else {
2361229984c5Sstefano_zampini     ierr = VecCopy(standard_rhs,pcbddc->original_rhs);CHKERRQ(ierr);
23626cc1294bSstefano_zampini   }
2363af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
2364229984c5Sstefano_zampini     /* interface pressure rhs */
2365022d8d2bSstefano_zampini     ierr = VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2366022d8d2bSstefano_zampini     ierr = VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2367229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2368229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
23696cc1294bSstefano_zampini     if (!mat_ctx->rhs_flip) {
2370229984c5Sstefano_zampini       ierr = VecScale(fetidp_flux_rhs,-1.);CHKERRQ(ierr);
2371229984c5Sstefano_zampini     }
23726cc1294bSstefano_zampini   }
2373c08af4c6SStefano Zampini   /*
2374c08af4c6SStefano Zampini      change of basis for physical rhs if needed
2375c08af4c6SStefano Zampini      It also changes the rhs in case of dirichlet boundaries
2376c08af4c6SStefano Zampini   */
23773738a8e6SStefano Zampini   ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,pcbddc->original_rhs,NULL);CHKERRQ(ierr);
2378fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
23793738a8e6SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcbddc->original_rhs,pcbddc->work_change);CHKERRQ(ierr);
23803738a8e6SStefano Zampini     work = pcbddc->work_change;
2381fc17d649SStefano Zampini    } else {
23823738a8e6SStefano Zampini     work = pcbddc->original_rhs;
2383fc17d649SStefano Zampini   }
23843425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
2385266e20e9SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2386266e20e9SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2387fb223d50SStefano Zampini   /* scale rhs since it should be unassembled */
2388fb223d50SStefano Zampini   /* TODO use counter scaling? (also below) */
2389266e20e9SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2390266e20e9SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2391674ae819SStefano Zampini   /* Apply partition of unity */
23923425bc38SStefano Zampini   ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
2393266e20e9SStefano Zampini   /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
23948eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
23953425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
239655c176c0SStefano Zampini     ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0);CHKERRQ(ierr);
23973425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
239855c176c0SStefano Zampini     ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0);CHKERRQ(ierr);
2399c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
24003425bc38SStefano Zampini     ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr);
24013425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr);
2402266e20e9SStefano Zampini     ierr = VecSet(work,0.0);CHKERRQ(ierr);
2403266e20e9SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2404266e20e9SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2405266e20e9SStefano Zampini     /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
2406266e20e9SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2407266e20e9SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
24083425bc38SStefano Zampini     ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
24093425bc38SStefano Zampini   }
24103425bc38SStefano Zampini   /* BDDC rhs */
24113425bc38SStefano Zampini   ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr);
24128eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
24133425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
24143425bc38SStefano Zampini   }
24153425bc38SStefano Zampini   /* apply BDDC */
2416580bdb30SBarry Smith   ierr = PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n);CHKERRQ(ierr);
2417dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
2418580bdb30SBarry Smith   ierr = PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n);CHKERRQ(ierr);
2419229984c5Sstefano_zampini 
24203425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
24213425bc38SStefano Zampini   ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr);
24223425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
24233425bc38SStefano Zampini   ierr = VecScatterEnd(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2424229984c5Sstefano_zampini   /* Add contribution to interface pressures */
2425229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
2426229984c5Sstefano_zampini     ierr = MatMult(mat_ctx->B_BB,pcis->vec1_B,mat_ctx->vP);CHKERRQ(ierr);
2427229984c5Sstefano_zampini     if (pcbddc->switch_static) {
2428229984c5Sstefano_zampini       ierr = MatMultAdd(mat_ctx->B_BI,pcis->vec1_D,mat_ctx->vP,mat_ctx->vP);CHKERRQ(ierr);
2429229984c5Sstefano_zampini     }
2430229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2431229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2432229984c5Sstefano_zampini   }
24333425bc38SStefano Zampini   PetscFunctionReturn(0);
24343425bc38SStefano Zampini }
24351e6b0712SBarry Smith 
24363425bc38SStefano Zampini /*@
24370f202f7eSStefano Zampini  PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side
24383425bc38SStefano Zampini 
24393425bc38SStefano Zampini    Collective
24403425bc38SStefano Zampini 
24413425bc38SStefano Zampini    Input Parameters:
24420f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix object obtained by a call to PCBDDCCreateFETIDPOperators
24430f202f7eSStefano Zampini -  standard_rhs    - the right-hand side of the original linear system
24443425bc38SStefano Zampini 
24453425bc38SStefano Zampini    Output Parameters:
24460f202f7eSStefano Zampini .  fetidp_flux_rhs - the right-hand side for the FETI-DP linear system
24473425bc38SStefano Zampini 
24483425bc38SStefano Zampini    Level: developer
24493425bc38SStefano Zampini 
24503425bc38SStefano Zampini    Notes:
24513425bc38SStefano Zampini 
24520f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetSolution
24533425bc38SStefano Zampini @*/
24543425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
24553425bc38SStefano Zampini {
2456674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
24573425bc38SStefano Zampini   PetscErrorCode ierr;
24583425bc38SStefano Zampini 
24593425bc38SStefano Zampini   PetscFunctionBegin;
2460266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1);
2461266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_rhs,VEC_CLASSID,2);
2462266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_rhs,VEC_CLASSID,3);
24633425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
2464163d334eSBarry Smith   ierr = PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr);
24653425bc38SStefano Zampini   PetscFunctionReturn(0);
24663425bc38SStefano Zampini }
24671e6b0712SBarry Smith 
24683425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
24693425bc38SStefano Zampini {
2470674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
24713425bc38SStefano Zampini   PC_IS*         pcis;
24723425bc38SStefano Zampini   PC_BDDC*       pcbddc;
24733425bc38SStefano Zampini   PetscErrorCode ierr;
2474229984c5Sstefano_zampini   Vec            work;
24753425bc38SStefano Zampini 
24763425bc38SStefano Zampini   PetscFunctionBegin;
24773425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
24783425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
24793425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
24803425bc38SStefano Zampini 
24813425bc38SStefano Zampini   /* apply B_delta^T */
2482af140850Sstefano_zampini   ierr = VecSet(pcis->vec1_B,0.);CHKERRQ(ierr);
24833425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
24843425bc38SStefano Zampini   ierr = VecScatterEnd(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
24853425bc38SStefano Zampini   ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
2486229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
2487229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2488229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2489229984c5Sstefano_zampini     ierr = MatMultAdd(mat_ctx->Bt_BB,mat_ctx->vP,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
2490229984c5Sstefano_zampini   }
2491229984c5Sstefano_zampini 
24923425bc38SStefano Zampini   /* compute rhs for BDDC application */
24933425bc38SStefano Zampini   ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr);
24948eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
24953425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
2496229984c5Sstefano_zampini     if (mat_ctx->l2g_p) {
2497229984c5Sstefano_zampini       ierr = VecScale(mat_ctx->vP,-1.);CHKERRQ(ierr);
2498229984c5Sstefano_zampini       ierr = MatMultAdd(mat_ctx->Bt_BI,mat_ctx->vP,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr);
24993425bc38SStefano Zampini     }
2500229984c5Sstefano_zampini   }
2501229984c5Sstefano_zampini 
25023425bc38SStefano Zampini   /* apply BDDC */
2503580bdb30SBarry Smith   ierr = PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n);CHKERRQ(ierr);
2504dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
2505229984c5Sstefano_zampini 
2506229984c5Sstefano_zampini   /* put values into global vector */
2507af140850Sstefano_zampini   if (pcbddc->ChangeOfBasisMatrix) work = pcbddc->work_change;
2508af140850Sstefano_zampini   else work = standard_sol;
2509229984c5Sstefano_zampini   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2510229984c5Sstefano_zampini   ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
25118eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
25123425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
25133425bc38SStefano Zampini     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr);
251400f6b531SStefano Zampini     ierr = VecAYPX(pcis->vec1_D,-1.0,mat_ctx->temp_solution_D);CHKERRQ(ierr);
251555c176c0SStefano Zampini     ierr = PetscLogEventBegin(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0);CHKERRQ(ierr);
251600f6b531SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr);
251755c176c0SStefano Zampini     ierr = PetscLogEventEnd(PC_BDDC_Solves[pcbddc->current_level][0],mat_ctx->pc,0,0,0);CHKERRQ(ierr);
2518c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
25193425bc38SStefano Zampini   }
2520229984c5Sstefano_zampini 
2521229984c5Sstefano_zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2522229984c5Sstefano_zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2523266e20e9SStefano Zampini   /* add p0 solution to final solution */
2524229984c5Sstefano_zampini   ierr = PCBDDCBenignGetOrSetP0(mat_ctx->pc,work,PETSC_FALSE);CHKERRQ(ierr);
2525fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2526af140850Sstefano_zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,work,standard_sol);CHKERRQ(ierr);
2527fc17d649SStefano Zampini   }
2528af140850Sstefano_zampini   ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr);
2529af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
2530229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2531229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2532229984c5Sstefano_zampini   }
25333425bc38SStefano Zampini   PetscFunctionReturn(0);
25343425bc38SStefano Zampini }
25351e6b0712SBarry Smith 
25365a1e936bSStefano Zampini static PetscErrorCode PCView_BDDCIPC(PC pc, PetscViewer viewer)
25375a1e936bSStefano Zampini {
25385a1e936bSStefano Zampini   PetscErrorCode ierr;
25395a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25405a1e936bSStefano Zampini   PetscBool      isascii;
25415a1e936bSStefano Zampini 
25425a1e936bSStefano Zampini   PetscFunctionBegin;
25433ec1f749SStefano Zampini   ierr = PCShellGetContext(pc,&bddcipc_ctx);CHKERRQ(ierr);
25445a1e936bSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
25455a1e936bSStefano Zampini   if (isascii) {
25465a1e936bSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"BDDC interface preconditioner\n");CHKERRQ(ierr);
25475a1e936bSStefano Zampini   }
25485a1e936bSStefano Zampini   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
25495a1e936bSStefano Zampini   ierr = PCView(bddcipc_ctx->bddc,viewer);CHKERRQ(ierr);
25505a1e936bSStefano Zampini   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
25515a1e936bSStefano Zampini   PetscFunctionReturn(0);
25525a1e936bSStefano Zampini }
25535a1e936bSStefano Zampini 
25545a1e936bSStefano Zampini static PetscErrorCode PCSetUp_BDDCIPC(PC pc)
25555a1e936bSStefano Zampini {
25565a1e936bSStefano Zampini   PetscErrorCode ierr;
25575a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25585a1e936bSStefano Zampini   PetscBool      isbddc;
25595a1e936bSStefano Zampini   Vec            vv;
25605a1e936bSStefano Zampini   IS             is;
25615a1e936bSStefano Zampini   PC_IS          *pcis;
25625a1e936bSStefano Zampini 
25635a1e936bSStefano Zampini   PetscFunctionBegin;
25643ec1f749SStefano Zampini   ierr = PCShellGetContext(pc,&bddcipc_ctx);CHKERRQ(ierr);
25655a1e936bSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)bddcipc_ctx->bddc,PCBDDC,&isbddc);CHKERRQ(ierr);
2566*98921bdaSJacob Faibussowitsch   if (!isbddc) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid type %s. Must be of type bddc",((PetscObject)bddcipc_ctx->bddc)->type_name);
25675a1e936bSStefano Zampini   ierr = PCSetUp(bddcipc_ctx->bddc);CHKERRQ(ierr);
25685a1e936bSStefano Zampini 
25695a1e936bSStefano Zampini   /* create interface scatter */
25705a1e936bSStefano Zampini   pcis = (PC_IS*)(bddcipc_ctx->bddc->data);
25715a1e936bSStefano Zampini   ierr = VecScatterDestroy(&bddcipc_ctx->g2l);CHKERRQ(ierr);
25725a1e936bSStefano Zampini   ierr = MatCreateVecs(pc->pmat,&vv,NULL);CHKERRQ(ierr);
25735a1e936bSStefano Zampini   ierr = ISRenumber(pcis->is_B_global,NULL,NULL,&is);CHKERRQ(ierr);
25749448b7f1SJunchao Zhang   ierr = VecScatterCreate(vv,is,pcis->vec1_B,NULL,&bddcipc_ctx->g2l);CHKERRQ(ierr);
25755a1e936bSStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
25765a1e936bSStefano Zampini   ierr = VecDestroy(&vv);CHKERRQ(ierr);
25775a1e936bSStefano Zampini   PetscFunctionReturn(0);
25785a1e936bSStefano Zampini }
25795a1e936bSStefano Zampini 
25805a1e936bSStefano Zampini static PetscErrorCode PCApply_BDDCIPC(PC pc, Vec r, Vec x)
25815a1e936bSStefano Zampini {
25825a1e936bSStefano Zampini   PetscErrorCode ierr;
25835a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25845a1e936bSStefano Zampini   PC_IS          *pcis;
25855a1e936bSStefano Zampini   VecScatter     tmps;
25865a1e936bSStefano Zampini 
25875a1e936bSStefano Zampini   PetscFunctionBegin;
25883ec1f749SStefano Zampini   ierr = PCShellGetContext(pc,&bddcipc_ctx);CHKERRQ(ierr);
25895a1e936bSStefano Zampini   pcis = (PC_IS*)(bddcipc_ctx->bddc->data);
25905a1e936bSStefano Zampini   tmps = pcis->global_to_B;
25915a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
25925a1e936bSStefano Zampini   ierr = PCBDDCScalingRestriction(bddcipc_ctx->bddc,r,pcis->vec1_B);CHKERRQ(ierr);
25935a1e936bSStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc,PETSC_FALSE);CHKERRQ(ierr);
25945a1e936bSStefano Zampini   ierr = PCBDDCScalingExtension(bddcipc_ctx->bddc,pcis->vec1_B,x);CHKERRQ(ierr);
25955a1e936bSStefano Zampini   pcis->global_to_B = tmps;
25965a1e936bSStefano Zampini   PetscFunctionReturn(0);
25975a1e936bSStefano Zampini }
25985a1e936bSStefano Zampini 
25995a1e936bSStefano Zampini static PetscErrorCode PCApplyTranspose_BDDCIPC(PC pc, Vec r, Vec x)
26005a1e936bSStefano Zampini {
26015a1e936bSStefano Zampini   PetscErrorCode ierr;
26025a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
26035a1e936bSStefano Zampini   PC_IS          *pcis;
26045a1e936bSStefano Zampini   VecScatter     tmps;
26055a1e936bSStefano Zampini 
26065a1e936bSStefano Zampini   PetscFunctionBegin;
26073ec1f749SStefano Zampini   ierr = PCShellGetContext(pc,&bddcipc_ctx);CHKERRQ(ierr);
26085a1e936bSStefano Zampini   pcis = (PC_IS*)(bddcipc_ctx->bddc->data);
26095a1e936bSStefano Zampini   tmps = pcis->global_to_B;
26105a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
26115a1e936bSStefano Zampini   ierr = PCBDDCScalingRestriction(bddcipc_ctx->bddc,r,pcis->vec1_B);CHKERRQ(ierr);
26125a1e936bSStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc,PETSC_TRUE);CHKERRQ(ierr);
26135a1e936bSStefano Zampini   ierr = PCBDDCScalingExtension(bddcipc_ctx->bddc,pcis->vec1_B,x);CHKERRQ(ierr);
26145a1e936bSStefano Zampini   pcis->global_to_B = tmps;
26155a1e936bSStefano Zampini   PetscFunctionReturn(0);
26165a1e936bSStefano Zampini }
26175a1e936bSStefano Zampini 
26185a1e936bSStefano Zampini static PetscErrorCode PCDestroy_BDDCIPC(PC pc)
26195a1e936bSStefano Zampini {
26205a1e936bSStefano Zampini   PetscErrorCode ierr;
26215a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
26225a1e936bSStefano Zampini 
26235a1e936bSStefano Zampini   PetscFunctionBegin;
26243ec1f749SStefano Zampini   ierr = PCShellGetContext(pc,&bddcipc_ctx);CHKERRQ(ierr);
26255a1e936bSStefano Zampini   ierr = PCDestroy(&bddcipc_ctx->bddc);CHKERRQ(ierr);
26265a1e936bSStefano Zampini   ierr = VecScatterDestroy(&bddcipc_ctx->g2l);CHKERRQ(ierr);
26275a1e936bSStefano Zampini   ierr = PetscFree(bddcipc_ctx);CHKERRQ(ierr);
26285a1e936bSStefano Zampini   PetscFunctionReturn(0);
26295a1e936bSStefano Zampini }
26305a1e936bSStefano Zampini 
26313425bc38SStefano Zampini /*@
26320f202f7eSStefano Zampini  PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system
26333425bc38SStefano Zampini 
26343425bc38SStefano Zampini    Collective
26353425bc38SStefano Zampini 
26363425bc38SStefano Zampini    Input Parameters:
26370f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators
26380f202f7eSStefano Zampini -  fetidp_flux_sol - the solution of the FETI-DP linear system
26393425bc38SStefano Zampini 
26403425bc38SStefano Zampini    Output Parameters:
26410f202f7eSStefano Zampini .  standard_sol    - the solution defined on the physical domain
26423425bc38SStefano Zampini 
26433425bc38SStefano Zampini    Level: developer
26443425bc38SStefano Zampini 
26453425bc38SStefano Zampini    Notes:
26463425bc38SStefano Zampini 
26470f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetRHS
26483425bc38SStefano Zampini @*/
26493425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
26503425bc38SStefano Zampini {
2651674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
26523425bc38SStefano Zampini   PetscErrorCode ierr;
26533425bc38SStefano Zampini 
26543425bc38SStefano Zampini   PetscFunctionBegin;
2655266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1);
2656266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_sol,VEC_CLASSID,2);
2657266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_sol,VEC_CLASSID,3);
26583425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
2659163d334eSBarry Smith   ierr = PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr);
26603425bc38SStefano Zampini   PetscFunctionReturn(0);
26613425bc38SStefano Zampini }
26621e6b0712SBarry Smith 
2663547c9a8eSstefano_zampini static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, PetscBool fully_redundant, const char* prefix, Mat *fetidp_mat, PC *fetidp_pc)
26643425bc38SStefano Zampini {
2665674ae819SStefano Zampini 
2666674ae819SStefano Zampini   FETIDPMat_ctx  fetidpmat_ctx;
26673425bc38SStefano Zampini   Mat            newmat;
2668674ae819SStefano Zampini   FETIDPPC_ctx   fetidppc_ctx;
26693425bc38SStefano Zampini   PC             newpc;
2670ce94432eSBarry Smith   MPI_Comm       comm;
26713425bc38SStefano Zampini   PetscErrorCode ierr;
26723425bc38SStefano Zampini 
26733425bc38SStefano Zampini   PetscFunctionBegin;
2674ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
267515579a77SStefano Zampini   /* FETI-DP matrix */
26763425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr);
26771720468bSStefano Zampini   fetidpmat_ctx->fully_redundant = fully_redundant;
26783425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr);
2679a5bb87b3Sstefano_zampini   ierr = MatCreateShell(comm,fetidpmat_ctx->n,fetidpmat_ctx->n,fetidpmat_ctx->N,fetidpmat_ctx->N,fetidpmat_ctx,&newmat);CHKERRQ(ierr);
268015579a77SStefano Zampini   ierr = PetscObjectSetName((PetscObject)newmat,!fetidpmat_ctx->l2g_lambda_only ? "F" : "G");CHKERRQ(ierr);
26813425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr);
2682edf7251bSStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT_TRANSPOSE,(void (*)(void))FETIDPMatMultTranspose);CHKERRQ(ierr);
26833425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr);
268415579a77SStefano Zampini   /* propagate MatOptions */
268515579a77SStefano Zampini   {
268615579a77SStefano Zampini     PC_BDDC   *pcbddc = (PC_BDDC*)fetidpmat_ctx->pc->data;
268715579a77SStefano Zampini     PetscBool issym;
268815579a77SStefano Zampini 
268915579a77SStefano Zampini     ierr = MatGetOption(pc->mat,MAT_SYMMETRIC,&issym);CHKERRQ(ierr);
269015579a77SStefano Zampini     if (issym || pcbddc->symmetric_primal) {
269115579a77SStefano Zampini       ierr = MatSetOption(newmat,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
269215579a77SStefano Zampini     }
269315579a77SStefano Zampini   }
2694547c9a8eSstefano_zampini   ierr = MatSetOptionsPrefix(newmat,prefix);CHKERRQ(ierr);
2695547c9a8eSstefano_zampini   ierr = MatAppendOptionsPrefix(newmat,"fetidp_");CHKERRQ(ierr);
26963425bc38SStefano Zampini   ierr = MatSetUp(newmat);CHKERRQ(ierr);
269715579a77SStefano Zampini   /* FETI-DP preconditioner */
26983425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr);
26993425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr);
27003425bc38SStefano Zampini   ierr = PCCreate(comm,&newpc);CHKERRQ(ierr);
2701e1214c54Sstefano_zampini   ierr = PCSetOperators(newpc,newmat,newmat);CHKERRQ(ierr);
2702e1214c54Sstefano_zampini   ierr = PCSetOptionsPrefix(newpc,prefix);CHKERRQ(ierr);
2703e1214c54Sstefano_zampini   ierr = PCAppendOptionsPrefix(newpc,"fetidp_");CHKERRQ(ierr);
2704399ffe99SStefano Zampini   ierr = PCSetErrorIfFailure(newpc,pc->erroriffailure);CHKERRQ(ierr);
270515579a77SStefano Zampini   if (!fetidpmat_ctx->l2g_lambda_only) { /* standard FETI-DP */
27063425bc38SStefano Zampini     ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
270715579a77SStefano Zampini     ierr = PCShellSetName(newpc,"FETI-DP multipliers");CHKERRQ(ierr);
27083425bc38SStefano Zampini     ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr);
27093425bc38SStefano Zampini     ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr);
2710edf7251bSStefano Zampini     ierr = PCShellSetApplyTranspose(newpc,FETIDPPCApplyTranspose);CHKERRQ(ierr);
2711c45b8d2dSstefano_zampini     ierr = PCShellSetView(newpc,FETIDPPCView);CHKERRQ(ierr);
27123425bc38SStefano Zampini     ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
27135a1e936bSStefano Zampini   } else { /* saddle-point FETI-DP */
27145a1e936bSStefano Zampini     Mat       M;
27155a1e936bSStefano Zampini     PetscInt  psize;
27165a1e936bSStefano Zampini     PetscBool fake = PETSC_FALSE, isfieldsplit;
2717e1214c54Sstefano_zampini 
271815579a77SStefano Zampini     ierr = ISViewFromOptions(fetidpmat_ctx->lagrange,NULL,"-lag_view");CHKERRQ(ierr);
271915579a77SStefano Zampini     ierr = ISViewFromOptions(fetidpmat_ctx->pressure,NULL,"-press_view");CHKERRQ(ierr);
2720e1214c54Sstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_PPmat",(PetscObject*)&M);CHKERRQ(ierr);
2721e1214c54Sstefano_zampini     ierr = PCSetType(newpc,PCFIELDSPLIT);CHKERRQ(ierr);
2722e1214c54Sstefano_zampini     ierr = PCFieldSplitSetIS(newpc,"lag",fetidpmat_ctx->lagrange);CHKERRQ(ierr);
2723e1214c54Sstefano_zampini     ierr = PCFieldSplitSetIS(newpc,"p",fetidpmat_ctx->pressure);CHKERRQ(ierr);
2724e1214c54Sstefano_zampini     ierr = PCFieldSplitSetType(newpc,PC_COMPOSITE_SCHUR);CHKERRQ(ierr);
272540c75d76SStefano Zampini     ierr = PCFieldSplitSetSchurFactType(newpc,PC_FIELDSPLIT_SCHUR_FACT_DIAG);CHKERRQ(ierr);
27265a1e936bSStefano Zampini     ierr = ISGetSize(fetidpmat_ctx->pressure,&psize);CHKERRQ(ierr);
27275a1e936bSStefano Zampini     if (psize != M->rmap->N) {
27285a1e936bSStefano Zampini       Mat      M2;
27295a1e936bSStefano Zampini       PetscInt lpsize;
27305a1e936bSStefano Zampini 
27315a1e936bSStefano Zampini       fake = PETSC_TRUE;
27325a1e936bSStefano Zampini       ierr = ISGetLocalSize(fetidpmat_ctx->pressure,&lpsize);CHKERRQ(ierr);
27335a1e936bSStefano Zampini       ierr = MatCreate(comm,&M2);CHKERRQ(ierr);
27345a1e936bSStefano Zampini       ierr = MatSetType(M2,MATAIJ);CHKERRQ(ierr);
27355a1e936bSStefano Zampini       ierr = MatSetSizes(M2,lpsize,lpsize,psize,psize);CHKERRQ(ierr);
27365a1e936bSStefano Zampini       ierr = MatSetUp(M2);CHKERRQ(ierr);
27375a1e936bSStefano Zampini       ierr = MatAssemblyBegin(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27385a1e936bSStefano Zampini       ierr = MatAssemblyEnd(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27395a1e936bSStefano Zampini       ierr = PCFieldSplitSetSchurPre(newpc,PC_FIELDSPLIT_SCHUR_PRE_USER,M2);CHKERRQ(ierr);
27405a1e936bSStefano Zampini       ierr = MatDestroy(&M2);CHKERRQ(ierr);
27415a1e936bSStefano Zampini     } else {
2742e1214c54Sstefano_zampini       ierr = PCFieldSplitSetSchurPre(newpc,PC_FIELDSPLIT_SCHUR_PRE_USER,M);CHKERRQ(ierr);
27435a1e936bSStefano Zampini     }
2744c096484dSStefano Zampini     ierr = PCFieldSplitSetSchurScale(newpc,1.0);CHKERRQ(ierr);
274515579a77SStefano Zampini 
274615579a77SStefano Zampini     /* we need to setfromoptions and setup here to access the blocks */
2747e1214c54Sstefano_zampini     ierr = PCSetFromOptions(newpc);CHKERRQ(ierr);
2748e1214c54Sstefano_zampini     ierr = PCSetUp(newpc);CHKERRQ(ierr);
2749e1214c54Sstefano_zampini 
27505a1e936bSStefano Zampini     /* user may have changed the type (e.g. -fetidp_pc_type none) */
27515a1e936bSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)newpc,PCFIELDSPLIT,&isfieldsplit);CHKERRQ(ierr);
27525a1e936bSStefano Zampini     if (isfieldsplit) {
27535a1e936bSStefano Zampini       KSP       *ksps;
27545a1e936bSStefano Zampini       PC        ppc,lagpc;
27555a1e936bSStefano Zampini       PetscInt  nn;
2756064a4176SStefano Zampini       PetscBool ismatis,matisok = PETSC_FALSE,check = PETSC_FALSE;
27575a1e936bSStefano Zampini 
2758e1214c54Sstefano_zampini       /* set the solver for the (0,0) block */
27595a1e936bSStefano Zampini       ierr = PCFieldSplitSchurGetSubKSP(newpc,&nn,&ksps);CHKERRQ(ierr);
27605a1e936bSStefano Zampini       if (!nn) { /* not of type PC_COMPOSITE_SCHUR */
276140c75d76SStefano Zampini         ierr = PCFieldSplitGetSubKSP(newpc,&nn,&ksps);CHKERRQ(ierr);
27625a1e936bSStefano Zampini         if (!fake) { /* pass pmat to the pressure solver */
27635a1e936bSStefano Zampini           Mat F;
27645a1e936bSStefano Zampini 
27655a1e936bSStefano Zampini           ierr = KSPGetOperators(ksps[1],&F,NULL);CHKERRQ(ierr);
27665a1e936bSStefano Zampini           ierr = KSPSetOperators(ksps[1],F,M);CHKERRQ(ierr);
27675a1e936bSStefano Zampini         }
27685a1e936bSStefano Zampini       } else {
27695a1e936bSStefano Zampini         PetscBool issym;
27705a1e936bSStefano Zampini         Mat       S;
27715a1e936bSStefano Zampini 
27725a1e936bSStefano Zampini         ierr = PCFieldSplitSchurGetS(newpc,&S);CHKERRQ(ierr);
27735a1e936bSStefano Zampini 
27745a1e936bSStefano Zampini         ierr = MatGetOption(newmat,MAT_SYMMETRIC,&issym);CHKERRQ(ierr);
27755a1e936bSStefano Zampini         if (issym) {
27765a1e936bSStefano Zampini           ierr = MatSetOption(S,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
27775a1e936bSStefano Zampini         }
27785a1e936bSStefano Zampini       }
27795a1e936bSStefano Zampini       ierr = KSPGetPC(ksps[0],&lagpc);CHKERRQ(ierr);
2780e1214c54Sstefano_zampini       ierr = PCSetType(lagpc,PCSHELL);CHKERRQ(ierr);
27815a1e936bSStefano Zampini       ierr = PCShellSetName(lagpc,"FETI-DP multipliers");CHKERRQ(ierr);
2782e1214c54Sstefano_zampini       ierr = PCShellSetContext(lagpc,fetidppc_ctx);CHKERRQ(ierr);
2783e1214c54Sstefano_zampini       ierr = PCShellSetApply(lagpc,FETIDPPCApply);CHKERRQ(ierr);
2784e1214c54Sstefano_zampini       ierr = PCShellSetApplyTranspose(lagpc,FETIDPPCApplyTranspose);CHKERRQ(ierr);
2785e1214c54Sstefano_zampini       ierr = PCShellSetView(lagpc,FETIDPPCView);CHKERRQ(ierr);
2786e1214c54Sstefano_zampini       ierr = PCShellSetDestroy(lagpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
27875a1e936bSStefano Zampini 
27885a1e936bSStefano Zampini       /* Olof's idea: interface Schur complement preconditioner for the mass matrix */
27895a1e936bSStefano Zampini       ierr = KSPGetPC(ksps[1],&ppc);CHKERRQ(ierr);
27905a1e936bSStefano Zampini       if (fake) {
27915a1e936bSStefano Zampini         BDDCIPC_ctx    bddcipc_ctx;
2792ff11fd76SStefano Zampini         PetscContainer c;
27935a1e936bSStefano Zampini 
27945a1e936bSStefano Zampini         matisok = PETSC_TRUE;
27955a1e936bSStefano Zampini 
27965a1e936bSStefano Zampini         /* create inner BDDC solver */
27975a1e936bSStefano Zampini         ierr = PetscNew(&bddcipc_ctx);CHKERRQ(ierr);
27985a1e936bSStefano Zampini         ierr = PCCreate(comm,&bddcipc_ctx->bddc);CHKERRQ(ierr);
27995a1e936bSStefano Zampini         ierr = PCSetType(bddcipc_ctx->bddc,PCBDDC);CHKERRQ(ierr);
28005a1e936bSStefano Zampini         ierr = PCSetOperators(bddcipc_ctx->bddc,M,M);CHKERRQ(ierr);
2801ff11fd76SStefano Zampini         ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_pCSR",(PetscObject*)&c);CHKERRQ(ierr);
2802ff11fd76SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)M,MATIS,&ismatis);CHKERRQ(ierr);
2803ff11fd76SStefano Zampini         if (c && ismatis) {
2804ff11fd76SStefano Zampini           Mat      lM;
2805ff11fd76SStefano Zampini           PetscInt *csr,n;
2806ff11fd76SStefano Zampini 
2807ff11fd76SStefano Zampini           ierr = MatISGetLocalMat(M,&lM);CHKERRQ(ierr);
2808ff11fd76SStefano Zampini           ierr = MatGetSize(lM,&n,NULL);CHKERRQ(ierr);
2809ff11fd76SStefano Zampini           ierr = PetscContainerGetPointer(c,(void**)&csr);CHKERRQ(ierr);
2810ff11fd76SStefano Zampini           ierr = PCBDDCSetLocalAdjacencyGraph(bddcipc_ctx->bddc,n,csr,csr + (n + 1),PETSC_COPY_VALUES);CHKERRQ(ierr);
2811ff11fd76SStefano Zampini           ierr = MatISRestoreLocalMat(M,&lM);CHKERRQ(ierr);
2812ff11fd76SStefano Zampini         }
28135a1e936bSStefano Zampini         ierr = PCSetOptionsPrefix(bddcipc_ctx->bddc,((PetscObject)ksps[1])->prefix);CHKERRQ(ierr);
28145a1e936bSStefano Zampini         ierr = PCSetErrorIfFailure(bddcipc_ctx->bddc,pc->erroriffailure);CHKERRQ(ierr);
28155a1e936bSStefano Zampini         ierr = PCSetFromOptions(bddcipc_ctx->bddc);CHKERRQ(ierr);
28165a1e936bSStefano Zampini 
28175a1e936bSStefano Zampini         /* wrap the interface application */
28185a1e936bSStefano Zampini         ierr = PCSetType(ppc,PCSHELL);CHKERRQ(ierr);
28195a1e936bSStefano Zampini         ierr = PCShellSetName(ppc,"FETI-DP pressure");CHKERRQ(ierr);
28205a1e936bSStefano Zampini         ierr = PCShellSetContext(ppc,bddcipc_ctx);CHKERRQ(ierr);
28215a1e936bSStefano Zampini         ierr = PCShellSetSetUp(ppc,PCSetUp_BDDCIPC);CHKERRQ(ierr);
28225a1e936bSStefano Zampini         ierr = PCShellSetApply(ppc,PCApply_BDDCIPC);CHKERRQ(ierr);
28235a1e936bSStefano Zampini         ierr = PCShellSetApplyTranspose(ppc,PCApplyTranspose_BDDCIPC);CHKERRQ(ierr);
28245a1e936bSStefano Zampini         ierr = PCShellSetView(ppc,PCView_BDDCIPC);CHKERRQ(ierr);
28255a1e936bSStefano Zampini         ierr = PCShellSetDestroy(ppc,PCDestroy_BDDCIPC);CHKERRQ(ierr);
28265a1e936bSStefano Zampini       }
28275a1e936bSStefano Zampini 
28285a1e936bSStefano Zampini       /* determine if we need to assemble M to construct a preconditioner */
28295a1e936bSStefano Zampini       if (!matisok) {
28305a1e936bSStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)M,MATIS,&ismatis);CHKERRQ(ierr);
28315a1e936bSStefano Zampini         ierr = PetscObjectTypeCompareAny((PetscObject)ppc,&matisok,PCBDDC,PCJACOBI,PCNONE,PCMG,"");CHKERRQ(ierr);
28325a1e936bSStefano Zampini         if (ismatis && !matisok) {
28335a1e936bSStefano Zampini           ierr = MatConvert(M,MATAIJ,MAT_INPLACE_MATRIX,&M);CHKERRQ(ierr);
28345a1e936bSStefano Zampini         }
28355a1e936bSStefano Zampini       }
2836064a4176SStefano Zampini 
2837064a4176SStefano Zampini       /* run the subproblems to check convergence */
2838064a4176SStefano Zampini       ierr = PetscOptionsGetBool(NULL,((PetscObject)newmat)->prefix,"-check_saddlepoint",&check,NULL);CHKERRQ(ierr);
2839064a4176SStefano Zampini       if (check) {
2840064a4176SStefano Zampini         PetscInt i;
2841064a4176SStefano Zampini 
2842064a4176SStefano Zampini         for (i=0;i<nn;i++) {
2843064a4176SStefano Zampini           KSP       kspC;
2844064a4176SStefano Zampini           PC        pc;
2845064a4176SStefano Zampini           Mat       F,pF;
2846064a4176SStefano Zampini           Vec       x,y;
2847064a4176SStefano Zampini           PetscBool isschur,prec = PETSC_TRUE;
2848064a4176SStefano Zampini 
2849064a4176SStefano Zampini           ierr = KSPCreate(PetscObjectComm((PetscObject)ksps[i]),&kspC);CHKERRQ(ierr);
2850064a4176SStefano Zampini           ierr = KSPSetOptionsPrefix(kspC,((PetscObject)ksps[i])->prefix);CHKERRQ(ierr);
2851064a4176SStefano Zampini           ierr = KSPAppendOptionsPrefix(kspC,"check_");CHKERRQ(ierr);
2852064a4176SStefano Zampini           ierr = KSPGetOperators(ksps[i],&F,&pF);CHKERRQ(ierr);
2853064a4176SStefano Zampini           ierr = PetscObjectTypeCompare((PetscObject)F,MATSCHURCOMPLEMENT,&isschur);CHKERRQ(ierr);
2854064a4176SStefano Zampini           if (isschur) {
2855064a4176SStefano Zampini             KSP  kspS,kspS2;
2856064a4176SStefano Zampini             Mat  A00,pA00,A10,A01,A11;
2857064a4176SStefano Zampini             char prefix[256];
2858064a4176SStefano Zampini 
2859064a4176SStefano Zampini             ierr = MatSchurComplementGetKSP(F,&kspS);CHKERRQ(ierr);
2860064a4176SStefano Zampini             ierr = MatSchurComplementGetSubMatrices(F,&A00,&pA00,&A01,&A10,&A11);CHKERRQ(ierr);
2861064a4176SStefano Zampini             ierr = MatCreateSchurComplement(A00,pA00,A01,A10,A11,&F);CHKERRQ(ierr);
2862064a4176SStefano Zampini             ierr = MatSchurComplementGetKSP(F,&kspS2);CHKERRQ(ierr);
2863064a4176SStefano Zampini             ierr = PetscSNPrintf(prefix,sizeof(prefix),"%sschur_",((PetscObject)kspC)->prefix);CHKERRQ(ierr);
2864064a4176SStefano Zampini             ierr = KSPSetOptionsPrefix(kspS2,prefix);CHKERRQ(ierr);
2865064a4176SStefano Zampini             ierr = KSPGetPC(kspS2,&pc);CHKERRQ(ierr);
2866064a4176SStefano Zampini             ierr = PCSetType(pc,PCKSP);CHKERRQ(ierr);
2867064a4176SStefano Zampini             ierr = PCKSPSetKSP(pc,kspS);CHKERRQ(ierr);
2868064a4176SStefano Zampini             ierr = KSPSetFromOptions(kspS2);CHKERRQ(ierr);
2869064a4176SStefano Zampini             ierr = KSPGetPC(kspS2,&pc);CHKERRQ(ierr);
2870064a4176SStefano Zampini             ierr = PCSetUseAmat(pc,PETSC_TRUE);CHKERRQ(ierr);
2871064a4176SStefano Zampini           } else {
2872064a4176SStefano Zampini             ierr = PetscObjectReference((PetscObject)F);CHKERRQ(ierr);
2873064a4176SStefano Zampini           }
2874064a4176SStefano Zampini           ierr = KSPSetFromOptions(kspC);CHKERRQ(ierr);
2875064a4176SStefano Zampini           ierr = PetscOptionsGetBool(NULL,((PetscObject)kspC)->prefix,"-preconditioned",&prec,NULL);CHKERRQ(ierr);
2876064a4176SStefano Zampini           if (prec)  {
2877064a4176SStefano Zampini             ierr = KSPGetPC(ksps[i],&pc);CHKERRQ(ierr);
2878064a4176SStefano Zampini             ierr = KSPSetPC(kspC,pc);CHKERRQ(ierr);
2879064a4176SStefano Zampini           }
2880064a4176SStefano Zampini           ierr = KSPSetOperators(kspC,F,pF);CHKERRQ(ierr);
2881064a4176SStefano Zampini           ierr = MatCreateVecs(F,&x,&y);CHKERRQ(ierr);
2882064a4176SStefano Zampini           ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
2883064a4176SStefano Zampini           ierr = MatMult(F,x,y);CHKERRQ(ierr);
2884064a4176SStefano Zampini           ierr = KSPSolve(kspC,y,x);CHKERRQ(ierr);
2885c0decd05SBarry Smith           ierr = KSPCheckSolve(kspC,pc,x);CHKERRQ(ierr);
2886064a4176SStefano Zampini           ierr = KSPDestroy(&kspC);CHKERRQ(ierr);
2887064a4176SStefano Zampini           ierr = MatDestroy(&F);CHKERRQ(ierr);
2888064a4176SStefano Zampini           ierr = VecDestroy(&x);CHKERRQ(ierr);
2889064a4176SStefano Zampini           ierr = VecDestroy(&y);CHKERRQ(ierr);
2890064a4176SStefano Zampini         }
2891064a4176SStefano Zampini       }
2892e1214c54Sstefano_zampini       ierr = PetscFree(ksps);CHKERRQ(ierr);
2893e1214c54Sstefano_zampini     }
28945a1e936bSStefano Zampini   }
28953425bc38SStefano Zampini   /* return pointers for objects created */
28963425bc38SStefano Zampini   *fetidp_mat = newmat;
28973425bc38SStefano Zampini   *fetidp_pc  = newpc;
28983425bc38SStefano Zampini   PetscFunctionReturn(0);
28993425bc38SStefano Zampini }
29001e6b0712SBarry Smith 
290194ef8ddeSSatish Balay /*@C
29020f202f7eSStefano Zampini  PCBDDCCreateFETIDPOperators - Create FETI-DP operators
29033425bc38SStefano Zampini 
29043425bc38SStefano Zampini    Collective
29053425bc38SStefano Zampini 
29063425bc38SStefano Zampini    Input Parameters:
29071720468bSStefano Zampini +  pc - the BDDC preconditioning context (setup should have been called before)
2908547c9a8eSstefano_zampini .  fully_redundant - true for a fully redundant set of Lagrange multipliers
2909547c9a8eSstefano_zampini -  prefix - optional options database prefix for the objects to be created (can be NULL)
291028509bceSStefano Zampini 
291128509bceSStefano Zampini    Output Parameters:
29120f202f7eSStefano Zampini +  fetidp_mat - shell FETI-DP matrix object
29130f202f7eSStefano Zampini -  fetidp_pc  - shell Dirichlet preconditioner for FETI-DP matrix
291428509bceSStefano Zampini 
29153425bc38SStefano Zampini    Level: developer
29163425bc38SStefano Zampini 
29173425bc38SStefano Zampini    Notes:
29180f202f7eSStefano Zampini      Currently the only operations provided for FETI-DP matrix are MatMult and MatMultTranspose
29193425bc38SStefano Zampini 
29200f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCMatFETIDPGetRHS, PCBDDCMatFETIDPGetSolution
29213425bc38SStefano Zampini @*/
2922547c9a8eSstefano_zampini PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc)
29233425bc38SStefano Zampini {
29243425bc38SStefano Zampini   PetscErrorCode ierr;
29253425bc38SStefano Zampini 
29263425bc38SStefano Zampini   PetscFunctionBegin;
29273425bc38SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
29283425bc38SStefano Zampini   if (pc->setupcalled) {
2929547c9a8eSstefano_zampini     ierr = PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,PetscBool,const char*,Mat*,PC*),(pc,fully_redundant,prefix,fetidp_mat,fetidp_pc));CHKERRQ(ierr);
29306080607fSStefano Zampini   } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"You must call PCSetup_BDDC() first");
29313425bc38SStefano Zampini   PetscFunctionReturn(0);
29323425bc38SStefano Zampini }
29330c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
2934da1bb401SStefano Zampini /*MC
2935da1bb401SStefano Zampini    PCBDDC - Balancing Domain Decomposition by Constraints.
29360c7d97c5SJed Brown 
2937be4a8d98Sprj-    An implementation of the BDDC preconditioner based on the bibliography found below.
293828509bceSStefano Zampini 
293928509bceSStefano Zampini    The matrix to be preconditioned (Pmat) must be of type MATIS.
294028509bceSStefano Zampini 
29410f202f7eSStefano Zampini    Currently works with MATIS matrices with local matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers.
294228509bceSStefano Zampini 
294328509bceSStefano Zampini    It also works with unsymmetric and indefinite problems.
294428509bceSStefano Zampini 
2945b6fdb6dfSStefano 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.
2946b6fdb6dfSStefano Zampini 
2947c7017625SStefano 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).
294828509bceSStefano Zampini 
29490f202f7eSStefano 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()
295030368db7SStefano Zampini    Additional information on dofs can be provided by using PCBDDCSetDofsSplitting(), PCBDDCSetDirichletBoundaries(), PCBDDCSetNeumannBoundaries(), and PCBDDCSetPrimalVerticesIS() and their local counterparts.
295128509bceSStefano Zampini 
29520f202f7eSStefano Zampini    Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). Non-singular modes are retained via SVD.
295328509bceSStefano Zampini 
29540f202f7eSStefano 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.
29550f202f7eSStefano Zampini    User defined change of basis can be passed to PCBDDC by using PCBDDCSetChangeOfBasisMat()
295628509bceSStefano Zampini 
29570f202f7eSStefano Zampini    The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using a MatPartitioning object.
295828509bceSStefano Zampini 
2959df4d28bfSStefano 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.
296028509bceSStefano Zampini 
29610f202f7eSStefano 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.
29620f202f7eSStefano Zampini 
2963d314f959SVaclav Hapla    Options Database Keys (some of them, run with -help for a complete list):
29640f202f7eSStefano Zampini 
2965a2b725a8SWilliam Gropp +    -pc_bddc_use_vertices <true> - use or not vertices in primal space
29660f202f7eSStefano Zampini .    -pc_bddc_use_edges <true> - use or not edges in primal space
29670f202f7eSStefano Zampini .    -pc_bddc_use_faces <false> - use or not faces in primal space
29680f202f7eSStefano Zampini .    -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems
29690f202f7eSStefano Zampini .    -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only)
29700f202f7eSStefano Zampini .    -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested
29710f202f7eSStefano Zampini .    -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1])
297228509bceSStefano Zampini .    -pc_bddc_levels <0> - maximum number of levels for multilevel
29730f202f7eSStefano 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)
29745459c157SBarry 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)
29750f202f7eSStefano Zampini .    -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling
297671f2caa7Sprj- .    -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)
2977bd2a564bSStefano 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)
297828509bceSStefano Zampini -    -pc_bddc_check_level <0> - set verbosity level of debugging output
297928509bceSStefano Zampini 
298028509bceSStefano Zampini    Options for Dirichlet, Neumann or coarse solver can be set with
298128509bceSStefano Zampini .vb
298228509bceSStefano Zampini       -pc_bddc_dirichlet_
298328509bceSStefano Zampini       -pc_bddc_neumann_
298428509bceSStefano Zampini       -pc_bddc_coarse_
298528509bceSStefano Zampini .ve
2986f9ff08acSPierre Jolivet    e.g. -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. PCBDDC uses by default KSPPREONLY and PCLU.
298728509bceSStefano Zampini 
29880f202f7eSStefano Zampini    When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified as
298928509bceSStefano Zampini .vb
2990312be037SStefano Zampini       -pc_bddc_dirichlet_lN_
2991312be037SStefano Zampini       -pc_bddc_neumann_lN_
2992312be037SStefano Zampini       -pc_bddc_coarse_lN_
299328509bceSStefano Zampini .ve
29940f202f7eSStefano Zampini    Note that level number ranges from the finest (0) to the coarsest (N).
29950f202f7eSStefano 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.
29960f202f7eSStefano Zampini .vb
29970f202f7eSStefano Zampini      -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3
29980f202f7eSStefano Zampini .ve
29990f202f7eSStefano 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
3000da1bb401SStefano Zampini 
3001be4a8d98Sprj-    References:
3002be4a8d98Sprj- +   [1] - C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149--168, March 2007
3003be4a8d98Sprj- .   [2] - 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
3004be4a8d98Sprj- .   [3] - J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", Computing Volume 83, Issue 2--3, pages 55--85, November 2008
3005be4a8d98Sprj- -   [4] - 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
3006be4a8d98Sprj- 
3007da1bb401SStefano Zampini    Level: intermediate
3008da1bb401SStefano Zampini 
3009e94cfbe0SPatrick Sanan    Developer Notes:
3010da1bb401SStefano Zampini 
3011da1bb401SStefano Zampini    Contributed by Stefano Zampini
3012da1bb401SStefano Zampini 
3013da1bb401SStefano Zampini .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
3014da1bb401SStefano Zampini M*/
3015b2573a8aSBarry Smith 
30168cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
3017da1bb401SStefano Zampini {
3018da1bb401SStefano Zampini   PetscErrorCode      ierr;
3019da1bb401SStefano Zampini   PC_BDDC             *pcbddc;
3020da1bb401SStefano Zampini 
3021da1bb401SStefano Zampini   PetscFunctionBegin;
3022b00a9115SJed Brown   ierr     = PetscNewLog(pc,&pcbddc);CHKERRQ(ierr);
30233ec1f749SStefano Zampini   pc->data = pcbddc;
3024da1bb401SStefano Zampini 
3025da1bb401SStefano Zampini   /* create PCIS data structure */
3026da1bb401SStefano Zampini   ierr = PCISCreate(pc);CHKERRQ(ierr);
3027da1bb401SStefano Zampini 
30289326c5c6Sstefano_zampini   /* create local graph structure */
30299326c5c6Sstefano_zampini   ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr);
30309326c5c6Sstefano_zampini 
30319326c5c6Sstefano_zampini   /* BDDC nonzero defaults */
30326d9e27e4SStefano Zampini   pcbddc->use_nnsp                  = PETSC_TRUE;
303308a5cf49SStefano Zampini   pcbddc->use_local_adj             = PETSC_TRUE;
303447d04d0dSStefano Zampini   pcbddc->use_vertices              = PETSC_TRUE;
303547d04d0dSStefano Zampini   pcbddc->use_edges                 = PETSC_TRUE;
30363301b35fSStefano Zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
303714f95afaSStefano Zampini   pcbddc->vertex_size               = 1;
3038c703fcc7SStefano Zampini   pcbddc->recompute_topography      = PETSC_TRUE;
303968457ee5SStefano Zampini   pcbddc->coarse_size               = -1;
304085c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
304147d04d0dSStefano Zampini   pcbddc->coarsening_ratio          = 8;
304257de7509SStefano Zampini   pcbddc->coarse_eqs_per_proc       = 1;
304327b6a85dSStefano Zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
30441e0482f5SStefano Zampini   pcbddc->nedfield                  = -1;
30451e0482f5SStefano Zampini   pcbddc->nedglobal                 = PETSC_TRUE;
3046be12c134Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
3047b96c3477SStefano Zampini   pcbddc->sub_schurs_layers         = -1;
3048bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[0]     = 0.0;
3049bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[1]     = 0.0;
3050b7eb3628SStefano Zampini 
3051da1bb401SStefano Zampini   /* function pointers */
3052da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
305393bd9ae7SStefano Zampini   pc->ops->applytranspose      = PCApplyTranspose_BDDC;
3054da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
3055da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
3056da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
30576b78500eSPatrick Sanan   pc->ops->view                = PCView_BDDC;
30580a545947SLisandro Dalcin   pc->ops->applyrichardson     = NULL;
30590a545947SLisandro Dalcin   pc->ops->applysymmetricleft  = NULL;
30600a545947SLisandro Dalcin   pc->ops->applysymmetricright = NULL;
3061534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
3062534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
30639326c5c6Sstefano_zampini   pc->ops->reset               = PCReset_BDDC;
3064da1bb401SStefano Zampini 
3065da1bb401SStefano Zampini   /* composing function */
3066a13144ffSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",PCBDDCSetDiscreteGradient_BDDC);CHKERRQ(ierr);
3067a198735bSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",PCBDDCSetDivergenceMat_BDDC);CHKERRQ(ierr);
3068906d46d4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",PCBDDCSetChangeOfBasisMat_BDDC);CHKERRQ(ierr);
3069674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
307030368db7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",PCBDDCSetPrimalVerticesIS_BDDC);CHKERRQ(ierr);
30713100ebe3SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesLocalIS_C",PCBDDCGetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
30723100ebe3SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesIS_C",PCBDDCGetPrimalVerticesIS_BDDC);CHKERRQ(ierr);
3073bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr);
30742b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC);CHKERRQ(ierr);
3075b8ffe317SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC);CHKERRQ(ierr);
30762b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC);CHKERRQ(ierr);
3077bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
307882ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",PCBDDCSetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
3079bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
308082ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",PCBDDCSetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
3081bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
308282ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",PCBDDCGetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
3083bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
308482ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",PCBDDCGetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
3085bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
308663602bcaSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",PCBDDCSetDofsSplittingLocal_BDDC);CHKERRQ(ierr);
3087bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
3088bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr);
3089bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr);
3090bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr);
3091a06fd7f2SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",PCPreSolveChangeRHS_BDDC);CHKERRQ(ierr);
3092ab8c8b98SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",PCSetCoordinates_BDDC);CHKERRQ(ierr);
3093da1bb401SStefano Zampini   PetscFunctionReturn(0);
3094da1bb401SStefano Zampini }
309543371fb9SStefano Zampini 
309643371fb9SStefano Zampini /*@C
309743371fb9SStefano Zampini  PCBDDCInitializePackage - This function initializes everything in the PCBDDC package. It is called
30988a690491SBarry Smith     from PCInitializePackage().
309943371fb9SStefano Zampini 
310043371fb9SStefano Zampini  Level: developer
310143371fb9SStefano Zampini 
310243371fb9SStefano Zampini  .seealso: PetscInitialize()
310343371fb9SStefano Zampini @*/
310443371fb9SStefano Zampini PetscErrorCode PCBDDCInitializePackage(void)
310543371fb9SStefano Zampini {
310643371fb9SStefano Zampini   PetscErrorCode ierr;
310743371fb9SStefano Zampini   int            i;
310843371fb9SStefano Zampini 
310943371fb9SStefano Zampini   PetscFunctionBegin;
311043371fb9SStefano Zampini   if (PCBDDCPackageInitialized) PetscFunctionReturn(0);
311143371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_TRUE;
311243371fb9SStefano Zampini   ierr = PetscRegisterFinalize(PCBDDCFinalizePackage);CHKERRQ(ierr);
311343371fb9SStefano Zampini 
311443371fb9SStefano Zampini   /* general events */
311543371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCTopo",PC_CLASSID,&PC_BDDC_Topology[0]);CHKERRQ(ierr);
311643371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCLKSP",PC_CLASSID,&PC_BDDC_LocalSolvers[0]);CHKERRQ(ierr);
311743371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCLWor",PC_CLASSID,&PC_BDDC_LocalWork[0]);CHKERRQ(ierr);
311843371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCCorr",PC_CLASSID,&PC_BDDC_CorrectionSetUp[0]);CHKERRQ(ierr);
31198ead10e4SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCASet",PC_CLASSID,&PC_BDDC_ApproxSetUp[0]);CHKERRQ(ierr);
31208ead10e4SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCAApp",PC_CLASSID,&PC_BDDC_ApproxApply[0]);CHKERRQ(ierr);
312143371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCCSet",PC_CLASSID,&PC_BDDC_CoarseSetUp[0]);CHKERRQ(ierr);
312243371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCCKSP",PC_CLASSID,&PC_BDDC_CoarseSolver[0]);CHKERRQ(ierr);
312343371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCAdap",PC_CLASSID,&PC_BDDC_AdaptiveSetUp[0]);CHKERRQ(ierr);
312443371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCScal",PC_CLASSID,&PC_BDDC_Scaling[0]);CHKERRQ(ierr);
312543371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCSchr",PC_CLASSID,&PC_BDDC_Schurs[0]);CHKERRQ(ierr);
312655c176c0SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCDirS",PC_CLASSID,&PC_BDDC_Solves[0][0]);CHKERRQ(ierr);
312755c176c0SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCNeuS",PC_CLASSID,&PC_BDDC_Solves[0][1]);CHKERRQ(ierr);
312855c176c0SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCCoaS",PC_CLASSID,&PC_BDDC_Solves[0][2]);CHKERRQ(ierr);
312943371fb9SStefano Zampini   for (i=1;i<PETSC_PCBDDC_MAXLEVELS;i++) {
313043371fb9SStefano Zampini     char ename[32];
313143371fb9SStefano Zampini 
313243371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCTopo l%02d",i);CHKERRQ(ierr);
313343371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Topology[i]);CHKERRQ(ierr);
313443371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCLKSP l%02d",i);CHKERRQ(ierr);
313543371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_LocalSolvers[i]);CHKERRQ(ierr);
313643371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCLWor l%02d",i);CHKERRQ(ierr);
313743371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_LocalWork[i]);CHKERRQ(ierr);
313843371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCCorr l%02d",i);CHKERRQ(ierr);
313943371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CorrectionSetUp[i]);CHKERRQ(ierr);
31408ead10e4SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCASet l%02d",i);CHKERRQ(ierr);
31418ead10e4SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_ApproxSetUp[i]);CHKERRQ(ierr);
31428ead10e4SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCAApp l%02d",i);CHKERRQ(ierr);
31438ead10e4SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_ApproxApply[i]);CHKERRQ(ierr);
314443371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCCSet l%02d",i);CHKERRQ(ierr);
314543371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CoarseSetUp[i]);CHKERRQ(ierr);
314643371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCCKSP l%02d",i);CHKERRQ(ierr);
314743371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CoarseSolver[i]);CHKERRQ(ierr);
314843371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCAdap l%02d",i);CHKERRQ(ierr);
314943371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_AdaptiveSetUp[i]);CHKERRQ(ierr);
315043371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCScal l%02d",i);CHKERRQ(ierr);
315143371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Scaling[i]);CHKERRQ(ierr);
315243371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCSchr l%02d",i);CHKERRQ(ierr);
315343371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Schurs[i]);CHKERRQ(ierr);
315455c176c0SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCDirS l%02d",i);CHKERRQ(ierr);
315555c176c0SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Solves[i][0]);CHKERRQ(ierr);
315655c176c0SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCNeuS l%02d",i);CHKERRQ(ierr);
315755c176c0SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Solves[i][1]);CHKERRQ(ierr);
315855c176c0SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCCoaS l%02d",i);CHKERRQ(ierr);
315955c176c0SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Solves[i][2]);CHKERRQ(ierr);
316043371fb9SStefano Zampini   }
316143371fb9SStefano Zampini   PetscFunctionReturn(0);
316243371fb9SStefano Zampini }
316343371fb9SStefano Zampini 
316443371fb9SStefano Zampini /*@C
316543371fb9SStefano Zampini  PCBDDCFinalizePackage - This function frees everything from the PCBDDC package. It is
316643371fb9SStefano Zampini     called from PetscFinalize() automatically.
316743371fb9SStefano Zampini 
316843371fb9SStefano Zampini  Level: developer
316943371fb9SStefano Zampini 
317043371fb9SStefano Zampini  .seealso: PetscFinalize()
317143371fb9SStefano Zampini @*/
317243371fb9SStefano Zampini PetscErrorCode PCBDDCFinalizePackage(void)
317343371fb9SStefano Zampini {
317443371fb9SStefano Zampini   PetscFunctionBegin;
317543371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_FALSE;
317643371fb9SStefano Zampini   PetscFunctionReturn(0);
317743371fb9SStefano Zampini }
3178