xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 71f2caa7a7aa9f53709ccd732c22ce159ac413e9)
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];
5443371fb9SStefano Zampini 
550369aaf7SStefano Zampini PetscErrorCode PCApply_BDDC(PC,Vec,Vec);
560369aaf7SStefano Zampini 
574416b707SBarry Smith PetscErrorCode PCSetFromOptions_BDDC(PetscOptionItems *PetscOptionsObject,PC pc)
580c7d97c5SJed Brown {
590c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
60e569e4e1SStefano Zampini   PetscInt       nt,i;
610c7d97c5SJed Brown   PetscErrorCode ierr;
620c7d97c5SJed Brown 
630c7d97c5SJed Brown   PetscFunctionBegin;
64e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"BDDC options");CHKERRQ(ierr);
658eeda7d8SStefano Zampini   /* Verbose debugging */
66a13144ffSStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_check_level","Verbose output for PCBDDC (intended for debug)","none",pcbddc->dbg_flag,&pcbddc->dbg_flag,NULL);CHKERRQ(ierr);
67a13144ffSStefano Zampini   /* Approximate solvers */
68c7017625SStefano 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);
69c7017625SStefano 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);
70c7017625SStefano 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);
71c7017625SStefano 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);
726b78500eSPatrick Sanan   /* Primal space customization */
7308a5cf49SStefano 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);
74be12c134Sstefano_zampini   ierr = PetscOptionsInt("-pc_bddc_graph_maxcount","Maximum number of shared subdomains for a connected component","none",pcbddc->graphmaxcount,&pcbddc->graphmaxcount,NULL);CHKERRQ(ierr);
751c7a958bSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_corner_selection","Activates face-based corner selection","none",pcbddc->corner_selection,&pcbddc->corner_selection,NULL);CHKERRQ(ierr);
768eeda7d8SStefano 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);
778eeda7d8SStefano 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);
788eeda7d8SStefano 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);
7914f95afaSStefano 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);
806d9e27e4SStefano 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);
816d9e27e4SStefano 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);
8214f95afaSStefano 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);
838eeda7d8SStefano Zampini   /* Change of basis */
84b9b85e73SStefano 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);
85b9b85e73SStefano 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);
86674ae819SStefano Zampini   if (!pcbddc->use_change_of_basis) {
87674ae819SStefano Zampini     pcbddc->use_change_on_faces = PETSC_FALSE;
88674ae819SStefano Zampini   }
898eeda7d8SStefano Zampini   /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */
908eeda7d8SStefano 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);
91e569e4e1SStefano 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);
92e569e4e1SStefano Zampini   i    = pcbddc->coarsening_ratio;
93e569e4e1SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","PCBDDCSetCoarseningRatio",i,&i,NULL);CHKERRQ(ierr);
94e569e4e1SStefano Zampini   ierr = PCBDDCSetCoarseningRatio(pc,i);CHKERRQ(ierr);
95e569e4e1SStefano Zampini   i    = pcbddc->max_levels;
96e569e4e1SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_levels","Set maximum number of levels for multilevel","PCBDDCSetLevels",i,&i,NULL);CHKERRQ(ierr);
97e569e4e1SStefano Zampini   ierr = PCBDDCSetLevels(pc,i);CHKERRQ(ierr);
98e569e4e1SStefano 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);
99323d395dSStefano 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);
100674ae819SStefano 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);
101b96c3477SStefano 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);
102b96c3477SStefano 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);
103b96c3477SStefano 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);
104683d3df6SStefano 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);
105bf3a8328SStefano 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);
106839e9adbSstefano_zampini   ierr = PetscOptionsBool("-pc_bddc_deluxe_singlemat","Collapse deluxe operators","none",pcbddc->deluxe_singlemat,&pcbddc->deluxe_singlemat,NULL);CHKERRQ(ierr);
107bf3a8328SStefano 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);
108bd2a564bSStefano Zampini   nt   = 2;
109bd2a564bSStefano Zampini   ierr = PetscOptionsRealArray("-pc_bddc_adaptive_threshold","Thresholds to be used for adaptive selection of constraints","none",pcbddc->adaptive_threshold,&nt,NULL);CHKERRQ(ierr);
110bd2a564bSStefano Zampini   if (nt == 1) pcbddc->adaptive_threshold[1] = pcbddc->adaptive_threshold[0];
11108122e43SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_adaptive_nmin","Minimum number of constraints per connected components","none",pcbddc->adaptive_nmin,&pcbddc->adaptive_nmin,NULL);CHKERRQ(ierr);
11208122e43SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_adaptive_nmax","Maximum number of constraints per connected components","none",pcbddc->adaptive_nmax,&pcbddc->adaptive_nmax,NULL);CHKERRQ(ierr);
1133301b35fSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_symmetric","Symmetric computation of primal basis functions","none",pcbddc->symmetric_primal,&pcbddc->symmetric_primal,NULL);CHKERRQ(ierr);
114b0c7d250SStefano 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);
115b3afcdbeSStefano 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);
116e9627c49SStefano 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);
11727b6a85dSStefano 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);
118a198735bSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nonetflux","Automatic computation of no-net-flux quadrature weights","none",pcbddc->compute_nonetflux,&pcbddc->compute_nonetflux,NULL);CHKERRQ(ierr);
1194f1b2e48SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_detect_disconnected","Detects disconnected subdomains","none",pcbddc->detect_disconnected,&pcbddc->detect_disconnected,NULL);CHKERRQ(ierr);
1208361f951SStefano 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);
12170c64980SStefano 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);
1220c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
1230c7d97c5SJed Brown   PetscFunctionReturn(0);
1240c7d97c5SJed Brown }
1256b78500eSPatrick Sanan 
1266b78500eSPatrick Sanan static PetscErrorCode PCView_BDDC(PC pc,PetscViewer viewer)
1276b78500eSPatrick Sanan {
1286b78500eSPatrick Sanan   PC_BDDC              *pcbddc = (PC_BDDC*)pc->data;
129e9627c49SStefano Zampini   PC_IS                *pcis = (PC_IS*)pc->data;
1306b78500eSPatrick Sanan   PetscErrorCode       ierr;
13171783a16SStefano Zampini   PetscBool            isascii;
132e9627c49SStefano Zampini   PetscSubcomm         subcomm;
133e9627c49SStefano Zampini   PetscViewer          subviewer;
1346b78500eSPatrick Sanan 
1356b78500eSPatrick Sanan   PetscFunctionBegin;
1366b78500eSPatrick Sanan   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1376b78500eSPatrick Sanan   /* ASCII viewer */
1386b78500eSPatrick Sanan   if (isascii) {
1394b2aedd3SStefano Zampini     PetscMPIInt   color,rank,size;
140fbad9177SStefano Zampini     PetscInt64    loc[7],gsum[6],gmax[6],gmin[6],totbenign;
141e9627c49SStefano Zampini     PetscScalar   interface_size;
142e9627c49SStefano Zampini     PetscReal     ratio1=0.,ratio2=0.;
143e9627c49SStefano Zampini     Vec           counter;
1446b78500eSPatrick Sanan 
145b74ba07aSstefano_zampini     if (!pc->setupcalled) {
146b74ba07aSstefano_zampini       ierr = PetscViewerASCIIPrintf(viewer,"  Partial information available: preconditioner has not been setup yet\n");CHKERRQ(ierr);
147b74ba07aSstefano_zampini     }
148efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use verbose output: %D\n",pcbddc->dbg_flag);CHKERRQ(ierr);
1496f0c0a6aSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Use user-defined CSR: %d\n",!!pcbddc->mat_graph->nvtxs_csr);CHKERRQ(ierr);
1506f0c0a6aSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Use local mat graph: %d\n",pcbddc->use_local_adj && !pcbddc->mat_graph->nvtxs_csr);CHKERRQ(ierr);
151e9627c49SStefano Zampini     if (pcbddc->mat_graph->twodim) {
152efd4aadfSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Connectivity graph topological dimension: 2\n");CHKERRQ(ierr);
153e9627c49SStefano Zampini     } else {
154efd4aadfSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Connectivity graph topological dimension: 3\n");CHKERRQ(ierr);
155e9627c49SStefano Zampini     }
156aefa1729SStefano Zampini     if (pcbddc->graphmaxcount != PETSC_MAX_INT) {
157efd4aadfSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Graph max count: %D\n",pcbddc->graphmaxcount);CHKERRQ(ierr);
158aefa1729SStefano Zampini     }
15950e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Use vertices: %d (vertex size %D)\n",pcbddc->use_vertices,pcbddc->vertex_size);CHKERRQ(ierr);
160efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use edges: %d\n",pcbddc->use_edges);CHKERRQ(ierr);
161efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use faces: %d\n",pcbddc->use_faces);CHKERRQ(ierr);
162efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use true near null space: %d\n",pcbddc->use_nnsp_true);CHKERRQ(ierr);
163efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use QR for single constraints on cc: %d\n",pcbddc->use_qr_single);CHKERRQ(ierr);
164efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use change of basis on local edge nodes: %d\n",pcbddc->use_change_of_basis);CHKERRQ(ierr);
165efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use change of basis on local face nodes: %d\n",pcbddc->use_change_on_faces);CHKERRQ(ierr);
166efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  User defined change of basis matrix: %d\n",!!pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
167efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Has change of basis matrix: %d\n",!!pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
168efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Eliminate dirichlet boundary dofs: %d\n",pcbddc->eliminate_dirdofs);CHKERRQ(ierr);
169efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Switch on static condensation ops around the interface preconditioner: %d\n",pcbddc->switch_static);CHKERRQ(ierr);
170efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use exact dirichlet trick: %d\n",pcbddc->use_exact_dirichlet_trick);CHKERRQ(ierr);
17150e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Multilevel max levels: %D\n",pcbddc->max_levels);CHKERRQ(ierr);
17250e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Multilevel coarsening ratio: %D\n",pcbddc->coarsening_ratio);CHKERRQ(ierr);
173efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use estimated eigs for coarse problem: %d\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
174efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use deluxe scaling: %d\n",pcbddc->use_deluxe_scaling);CHKERRQ(ierr);
175efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use deluxe zerorows: %d\n",pcbddc->deluxe_zerorows);CHKERRQ(ierr);
176efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use deluxe singlemat: %d\n",pcbddc->deluxe_singlemat);CHKERRQ(ierr);
177efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Rebuild interface graph for Schur principal minors: %d\n",pcbddc->sub_schurs_rebuild);CHKERRQ(ierr);
17850e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Number of dofs' layers for the computation of principal minors: %D\n",pcbddc->sub_schurs_layers);CHKERRQ(ierr);
179efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use user CSR graph to compute successive layers: %d\n",pcbddc->sub_schurs_use_useradj);CHKERRQ(ierr);
180bd2a564bSStefano Zampini     if (pcbddc->adaptive_threshold[1] != pcbddc->adaptive_threshold[0]) {
181bd2a564bSStefano 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);
182bd2a564bSStefano Zampini     } else {
183bd2a564bSStefano 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);
184bd2a564bSStefano Zampini     }
18550e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Min constraints / connected component: %D\n",pcbddc->adaptive_nmin);CHKERRQ(ierr);
18650e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Max constraints / connected component: %D\n",pcbddc->adaptive_nmax);CHKERRQ(ierr);
187efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Invert exact Schur complement for adaptive selection: %d\n",pcbddc->sub_schurs_exact_schur);CHKERRQ(ierr);
188efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Symmetric computation of primal basis functions: %d\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
18950e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Num. Procs. to map coarse adjacency list: %D\n",pcbddc->coarse_adj_red);CHKERRQ(ierr);
19050e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Coarse eqs per proc (significant at the coarsest level): %D\n",pcbddc->coarse_eqs_per_proc);CHKERRQ(ierr);
1918361f951SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Detect disconnected: %d (filter %d)\n",pcbddc->detect_disconnected,pcbddc->detect_disconnected_filter);CHKERRQ(ierr);
192efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Benign subspace trick: %d (change explicit %d)\n",pcbddc->benign_saddle_point,pcbddc->benign_change_explicit);CHKERRQ(ierr);
193efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Benign subspace trick is active: %d\n",pcbddc->benign_have_null);CHKERRQ(ierr);
19415579a77SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Algebraic computation of no-net-flux: %d\n",pcbddc->compute_nonetflux);CHKERRQ(ierr);
195b74ba07aSstefano_zampini     if (!pc->setupcalled) PetscFunctionReturn(0);
1966b78500eSPatrick Sanan 
197fbad9177SStefano Zampini     /* compute interface size */
198e9627c49SStefano Zampini     ierr = VecSet(pcis->vec1_B,1.0);CHKERRQ(ierr);
199e9627c49SStefano Zampini     ierr = MatCreateVecs(pc->pmat,&counter,0);CHKERRQ(ierr);
200e9627c49SStefano Zampini     ierr = VecSet(counter,0.0);CHKERRQ(ierr);
201e9627c49SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
202e9627c49SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
203e9627c49SStefano Zampini     ierr = VecSum(counter,&interface_size);CHKERRQ(ierr);
204e9627c49SStefano Zampini     ierr = VecDestroy(&counter);CHKERRQ(ierr);
205fbad9177SStefano Zampini 
206fbad9177SStefano Zampini     /* compute some statistics on the domain decomposition */
207e9627c49SStefano Zampini     gsum[0] = 1;
208fbad9177SStefano Zampini     gsum[1] = gsum[2] = gsum[3] = gsum[4] = gsum[5] = 0;
209e9627c49SStefano Zampini     loc[0]  = !!pcis->n;
210e9627c49SStefano Zampini     loc[1]  = pcis->n - pcis->n_B;
211e9627c49SStefano Zampini     loc[2]  = pcis->n_B;
212e9627c49SStefano Zampini     loc[3]  = pcbddc->local_primal_size;
213345ecf6cSStefano Zampini     loc[4]  = pcis->n;
214fbad9177SStefano Zampini     loc[5]  = pcbddc->n_local_subs > 0 ? pcbddc->n_local_subs : (pcis->n ? 1 : 0);
215fbad9177SStefano Zampini     loc[6]  = pcbddc->benign_n;
216fbad9177SStefano Zampini     ierr = MPI_Reduce(loc,gsum,6,MPIU_INT64,MPI_SUM,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
217fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = -1;
218fbad9177SStefano Zampini     ierr = MPI_Reduce(loc,gmax,6,MPIU_INT64,MPI_MAX,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
219fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = PETSC_MAX_INT;
220fbad9177SStefano Zampini     ierr = MPI_Reduce(loc,gmin,6,MPIU_INT64,MPI_MIN,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
221fbad9177SStefano Zampini     ierr = MPI_Reduce(&loc[6],&totbenign,1,MPIU_INT64,MPI_SUM,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
222e9627c49SStefano Zampini     if (pcbddc->coarse_size) {
223e9627c49SStefano Zampini       ratio1 = pc->pmat->rmap->N/(1.*pcbddc->coarse_size);
224e9627c49SStefano Zampini       ratio2 = PetscRealPart(interface_size)/pcbddc->coarse_size;
225e9627c49SStefano Zampini     }
226efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"********************************** STATISTICS AT LEVEL %d **********************************\n",pcbddc->current_level);CHKERRQ(ierr);
22750e0721cSStefano 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);
22850e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Coarsening ratios: all/coarse %D interface/coarse %D\n",(PetscInt)ratio1,(PetscInt)ratio2);CHKERRQ(ierr);
22950e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Active processes : %D\n",(PetscInt)gsum[0]);CHKERRQ(ierr);
23050e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Total subdomains : %D\n",(PetscInt)gsum[5]);CHKERRQ(ierr);
231345ecf6cSStefano Zampini     if (pcbddc->benign_have_null) {
23250e0721cSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"  Benign subs      : %D\n",(PetscInt)totbenign);CHKERRQ(ierr);
233345ecf6cSStefano Zampini     }
23450e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Dofs type        :\tMIN\tMAX\tMEAN\n");CHKERRQ(ierr);
23550e0721cSStefano 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);
23650e0721cSStefano 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);
23750e0721cSStefano 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);
23850e0721cSStefano 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);
23950e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Local     subs   :\t%D\t%D\n"    ,(PetscInt)gmin[5],(PetscInt)gmax[5]);CHKERRQ(ierr);
24015579a77SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
24115579a77SStefano Zampini 
24215579a77SStefano Zampini     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
24315579a77SStefano Zampini 
24415579a77SStefano Zampini     /* local solvers */
24515579a77SStefano Zampini     ierr = PetscViewerGetSubViewer(viewer,PetscObjectComm((PetscObject)pcbddc->ksp_D),&subviewer);CHKERRQ(ierr);
24615579a77SStefano Zampini     if (!rank) {
24715579a77SStefano Zampini       ierr = PetscViewerASCIIPrintf(subviewer,"--- Interior solver (rank 0)\n");CHKERRQ(ierr);
24815579a77SStefano Zampini       ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr);
24915579a77SStefano Zampini       ierr = KSPView(pcbddc->ksp_D,subviewer);CHKERRQ(ierr);
25015579a77SStefano Zampini       ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr);
25115579a77SStefano Zampini       ierr = PetscViewerASCIIPrintf(subviewer,"--- Correction solver (rank 0)\n");CHKERRQ(ierr);
25215579a77SStefano Zampini       ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr);
25315579a77SStefano Zampini       ierr = KSPView(pcbddc->ksp_R,subviewer);CHKERRQ(ierr);
25415579a77SStefano Zampini       ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr);
25515579a77SStefano Zampini       ierr = PetscViewerFlush(subviewer);CHKERRQ(ierr);
25615579a77SStefano Zampini     }
25715579a77SStefano Zampini     ierr = PetscViewerRestoreSubViewer(viewer,PetscObjectComm((PetscObject)pcbddc->ksp_D),&subviewer);CHKERRQ(ierr);
25827b6a85dSStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
259e9627c49SStefano Zampini 
260fbad9177SStefano Zampini     /* the coarse problem can be handled by a different communicator */
261e9627c49SStefano Zampini     if (pcbddc->coarse_ksp) color = 1;
262e9627c49SStefano Zampini     else color = 0;
2634b2aedd3SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
264e9627c49SStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)pc),&subcomm);CHKERRQ(ierr);
2654b2aedd3SStefano Zampini     ierr = PetscSubcommSetNumber(subcomm,PetscMin(size,2));CHKERRQ(ierr);
266e9627c49SStefano Zampini     ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
267e9627c49SStefano Zampini     ierr = PetscViewerGetSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer);CHKERRQ(ierr);
268e9627c49SStefano Zampini     if (color == 1) {
26915579a77SStefano Zampini       ierr = PetscViewerASCIIPrintf(subviewer,"--- Coarse solver\n");CHKERRQ(ierr);
27015579a77SStefano Zampini       ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr);
271e9627c49SStefano Zampini       ierr = KSPView(pcbddc->coarse_ksp,subviewer);CHKERRQ(ierr);
27215579a77SStefano Zampini       ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr);
273e9627c49SStefano Zampini       ierr = PetscViewerFlush(subviewer);CHKERRQ(ierr);
274e9627c49SStefano Zampini     }
275e9627c49SStefano Zampini     ierr = PetscViewerRestoreSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer);CHKERRQ(ierr);
276e9627c49SStefano Zampini     ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
277e9627c49SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
278e9627c49SStefano Zampini   }
2796b78500eSPatrick Sanan   PetscFunctionReturn(0);
2806b78500eSPatrick Sanan }
281a13144ffSStefano Zampini 
2821e0482f5SStefano Zampini static PetscErrorCode PCBDDCSetDiscreteGradient_BDDC(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
283a13144ffSStefano Zampini {
284a13144ffSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
285a13144ffSStefano Zampini   PetscErrorCode ierr;
286a13144ffSStefano Zampini 
287a13144ffSStefano Zampini   PetscFunctionBegin;
288a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)G);CHKERRQ(ierr);
289a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
290a13144ffSStefano Zampini   pcbddc->discretegradient = G;
291a13144ffSStefano Zampini   pcbddc->nedorder         = order > 0 ? order : -order;
292495a2a07SStefano Zampini   pcbddc->nedfield         = field;
2931e0482f5SStefano Zampini   pcbddc->nedglobal        = global;
2941e0482f5SStefano Zampini   pcbddc->conforming       = conforming;
295a13144ffSStefano Zampini   PetscFunctionReturn(0);
296a13144ffSStefano Zampini }
297a13144ffSStefano Zampini 
298a13144ffSStefano Zampini /*@
299a13144ffSStefano Zampini  PCBDDCSetDiscreteGradient - Sets the discrete gradient
300a13144ffSStefano Zampini 
301a13144ffSStefano Zampini    Collective on PC
302a13144ffSStefano Zampini 
303a13144ffSStefano Zampini    Input Parameters:
304a13144ffSStefano Zampini +  pc         - the preconditioning context
305a13144ffSStefano Zampini .  G          - the discrete gradient matrix (should be in AIJ format)
306a13144ffSStefano Zampini .  order      - the order of the Nedelec space (1 for the lowest order)
307495a2a07SStefano Zampini .  field      - the field id of the Nedelec dofs (not used if the fields have not been specified)
3081e0482f5SStefano Zampini .  global     - the type of global ordering for the rows of G
309a13144ffSStefano Zampini -  conforming - whether the mesh is conforming or not
310a13144ffSStefano Zampini 
311a13144ffSStefano Zampini    Level: advanced
312a13144ffSStefano Zampini 
31395452b02SPatrick Sanan    Notes:
31495452b02SPatrick Sanan     The discrete gradient matrix G is used to analyze the subdomain edges, and it should not contain any zero entry.
315495a2a07SStefano Zampini           For variable order spaces, the order should be set to zero.
3161e0482f5SStefano Zampini           If global is true, the rows of G should be given in global ordering for the whole dofs;
3171e0482f5SStefano Zampini           if false, the ordering should be global for the Nedelec field.
3181e0482f5SStefano 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
3191e0482f5SStefano Zampini           and geid the one for the Nedelec field.
320a13144ffSStefano Zampini 
321495a2a07SStefano Zampini .seealso: PCBDDC,PCBDDCSetDofsSplitting(),PCBDDCSetDofsSplittingLocal()
322a13144ffSStefano Zampini @*/
3231e0482f5SStefano Zampini PetscErrorCode PCBDDCSetDiscreteGradient(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
324a13144ffSStefano Zampini {
325a13144ffSStefano Zampini   PetscErrorCode ierr;
326a13144ffSStefano Zampini 
327a13144ffSStefano Zampini   PetscFunctionBegin;
328a13144ffSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
329a13144ffSStefano Zampini   PetscValidHeaderSpecific(G,MAT_CLASSID,2);
330a13144ffSStefano Zampini   PetscValidLogicalCollectiveInt(pc,order,3);
3311e0482f5SStefano Zampini   PetscValidLogicalCollectiveInt(pc,field,4);
3321e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc,global,5);
3331e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc,conforming,6);
3341e0482f5SStefano Zampini   PetscCheckSameComm(pc,1,G,2);
3351e0482f5SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDiscreteGradient_C",(PC,Mat,PetscInt,PetscInt,PetscBool,PetscBool),(pc,G,order,field,global,conforming));CHKERRQ(ierr);
336a13144ffSStefano Zampini   PetscFunctionReturn(0);
337a13144ffSStefano Zampini }
338a13144ffSStefano Zampini 
3398ae0ca82SStefano Zampini static PetscErrorCode PCBDDCSetDivergenceMat_BDDC(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
340a198735bSStefano Zampini {
341a198735bSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
342a198735bSStefano Zampini   PetscErrorCode ierr;
3436b78500eSPatrick Sanan 
344a198735bSStefano Zampini   PetscFunctionBegin;
345a198735bSStefano Zampini   ierr = PetscObjectReference((PetscObject)divudotp);CHKERRQ(ierr);
346a198735bSStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
347a198735bSStefano Zampini   pcbddc->divudotp = divudotp;
3488ae0ca82SStefano Zampini   pcbddc->divudotp_trans = trans;
349a198735bSStefano Zampini   pcbddc->compute_nonetflux = PETSC_TRUE;
350a198735bSStefano Zampini   if (vl2l) {
351a198735bSStefano Zampini     ierr = PetscObjectReference((PetscObject)vl2l);CHKERRQ(ierr);
352fa23a32eSStefano Zampini     ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
353a198735bSStefano Zampini     pcbddc->divudotp_vl2l = vl2l;
354a198735bSStefano Zampini   }
355a198735bSStefano Zampini   PetscFunctionReturn(0);
356a198735bSStefano Zampini }
3573d996552SStefano Zampini 
358a198735bSStefano Zampini /*@
359a198735bSStefano Zampini  PCBDDCSetDivergenceMat - Sets the linear operator representing \int_\Omega \div {\bf u} \cdot p dx
360a198735bSStefano Zampini 
361a198735bSStefano Zampini    Collective on PC
362a198735bSStefano Zampini 
363a198735bSStefano Zampini    Input Parameters:
364a198735bSStefano Zampini +  pc - the preconditioning context
365a198735bSStefano Zampini .  divudotp - the matrix (must be of type MATIS)
3668ae0ca82SStefano Zampini .  trans - if trans if false (resp. true), then pressures are in the test (trial) space and velocities are in the trial (test) space.
36705a3bf82SStefano 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
368a198735bSStefano Zampini 
369a198735bSStefano Zampini    Level: advanced
370a198735bSStefano Zampini 
37195452b02SPatrick Sanan    Notes:
37295452b02SPatrick Sanan     This auxiliary matrix is used to compute quadrature weights representing the net-flux across subdomain boundaries
37305a3bf82SStefano Zampini           If vl2l is NULL, the local ordering for velocities in divudotp should match that of the preconditioning matrix
374a198735bSStefano Zampini 
375a198735bSStefano Zampini .seealso: PCBDDC
376a198735bSStefano Zampini @*/
3778ae0ca82SStefano Zampini PetscErrorCode PCBDDCSetDivergenceMat(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
378a198735bSStefano Zampini {
379a198735bSStefano Zampini   PetscBool      ismatis;
380a198735bSStefano Zampini   PetscErrorCode ierr;
381a198735bSStefano Zampini 
382a198735bSStefano Zampini   PetscFunctionBegin;
383a198735bSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
384a198735bSStefano Zampini   PetscValidHeaderSpecific(divudotp,MAT_CLASSID,2);
385a198735bSStefano Zampini   PetscCheckSameComm(pc,1,divudotp,2);
3868ae0ca82SStefano Zampini   PetscValidLogicalCollectiveBool(pc,trans,3);
3871b24a7afSStefano Zampini   if (vl2l) PetscValidHeaderSpecific(vl2l,IS_CLASSID,4);
388a198735bSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)divudotp,MATIS,&ismatis);CHKERRQ(ierr);
389a198735bSStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Divergence matrix needs to be of type MATIS");
3908ae0ca82SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDivergenceMat_C",(PC,Mat,PetscBool,IS),(pc,divudotp,trans,vl2l));CHKERRQ(ierr);
391a198735bSStefano Zampini   PetscFunctionReturn(0);
392a198735bSStefano Zampini }
3932d505d7fSStefano Zampini 
3941dd7afcfSStefano Zampini static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change, PetscBool interior)
395b9b85e73SStefano Zampini {
396b9b85e73SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
397b9b85e73SStefano Zampini   PetscErrorCode ierr;
398b9b85e73SStefano Zampini 
399b9b85e73SStefano Zampini   PetscFunctionBegin;
400b9b85e73SStefano Zampini   ierr = PetscObjectReference((PetscObject)change);CHKERRQ(ierr);
40156282151SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
402b9b85e73SStefano Zampini   pcbddc->user_ChangeOfBasisMatrix = change;
4031dd7afcfSStefano Zampini   pcbddc->change_interior = interior;
404b9b85e73SStefano Zampini   PetscFunctionReturn(0);
405b9b85e73SStefano Zampini }
406b9b85e73SStefano Zampini /*@
407906d46d4SStefano Zampini  PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs
408b9b85e73SStefano Zampini 
409b9b85e73SStefano Zampini    Collective on PC
410b9b85e73SStefano Zampini 
411b9b85e73SStefano Zampini    Input Parameters:
412b9b85e73SStefano Zampini +  pc - the preconditioning context
4131dd7afcfSStefano Zampini .  change - the change of basis matrix
4141dd7afcfSStefano Zampini -  interior - whether or not the change of basis modifies interior dofs
415b9b85e73SStefano Zampini 
416b9b85e73SStefano Zampini    Level: intermediate
417b9b85e73SStefano Zampini 
418b9b85e73SStefano Zampini    Notes:
419b9b85e73SStefano Zampini 
420b9b85e73SStefano Zampini .seealso: PCBDDC
421b9b85e73SStefano Zampini @*/
4221dd7afcfSStefano Zampini PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change, PetscBool interior)
423b9b85e73SStefano Zampini {
424b9b85e73SStefano Zampini   PetscErrorCode ierr;
425b9b85e73SStefano Zampini 
426b9b85e73SStefano Zampini   PetscFunctionBegin;
427b9b85e73SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
428b9b85e73SStefano Zampini   PetscValidHeaderSpecific(change,MAT_CLASSID,2);
429906d46d4SStefano Zampini   PetscCheckSameComm(pc,1,change,2);
430906d46d4SStefano Zampini   if (pc->mat) {
431906d46d4SStefano Zampini     PetscInt rows_c,cols_c,rows,cols;
432906d46d4SStefano Zampini     ierr = MatGetSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
433906d46d4SStefano Zampini     ierr = MatGetSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
434e0fe2d75SToby Isaac     if (rows_c != rows) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of rows for change of basis matrix! %D != %D",rows_c,rows);
435e0fe2d75SToby Isaac     if (cols_c != cols) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of columns for change of basis matrix! %D != %D",cols_c,cols);
436906d46d4SStefano Zampini     ierr = MatGetLocalSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
437906d46d4SStefano Zampini     ierr = MatGetLocalSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
438e0fe2d75SToby Isaac     if (rows_c != rows) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of local rows for change of basis matrix! %D != %D",rows_c,rows);
439e0fe2d75SToby Isaac     if (cols_c != cols) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of local columns for change of basis matrix! %D != %D",cols_c,cols);
440906d46d4SStefano Zampini   }
4411dd7afcfSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetChangeOfBasisMat_C",(PC,Mat,PetscBool),(pc,change,interior));CHKERRQ(ierr);
442b9b85e73SStefano Zampini   PetscFunctionReturn(0);
443b9b85e73SStefano Zampini }
4442d505d7fSStefano Zampini 
44530368db7SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesIS_BDDC(PC pc, IS PrimalVertices)
44630368db7SStefano Zampini {
44730368db7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
44856282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
44930368db7SStefano Zampini   PetscErrorCode ierr;
45030368db7SStefano Zampini 
45130368db7SStefano Zampini   PetscFunctionBegin;
45256282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
45356282151SStefano Zampini   if (pcbddc->user_primal_vertices) {
45456282151SStefano Zampini     ierr = ISEqual(PrimalVertices,pcbddc->user_primal_vertices,&isequal);CHKERRQ(ierr);
45556282151SStefano Zampini   }
45630368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
45730368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
45830368db7SStefano Zampini   pcbddc->user_primal_vertices = PrimalVertices;
45956282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
46030368db7SStefano Zampini   PetscFunctionReturn(0);
46130368db7SStefano Zampini }
462ab8c8b98SStefano Zampini 
46330368db7SStefano Zampini /*@
46430368db7SStefano Zampini  PCBDDCSetPrimalVerticesIS - Set additional user defined primal vertices in PCBDDC
46530368db7SStefano Zampini 
46630368db7SStefano Zampini    Collective
46730368db7SStefano Zampini 
46830368db7SStefano Zampini    Input Parameters:
46930368db7SStefano Zampini +  pc - the preconditioning context
47030368db7SStefano Zampini -  PrimalVertices - index set of primal vertices in global numbering (can be empty)
47130368db7SStefano Zampini 
47230368db7SStefano Zampini    Level: intermediate
47330368db7SStefano Zampini 
47430368db7SStefano Zampini    Notes:
47530368db7SStefano Zampini      Any process can list any global node
47630368db7SStefano Zampini 
4773100ebe3SStefano Zampini .seealso: PCBDDC, PCBDDCGetPrimalVerticesIS(), PCBDDCSetPrimalVerticesLocalIS(), PCBDDCGetPrimalVerticesLocalIS()
47830368db7SStefano Zampini @*/
47930368db7SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesIS(PC pc, IS PrimalVertices)
48030368db7SStefano Zampini {
48130368db7SStefano Zampini   PetscErrorCode ierr;
48230368db7SStefano Zampini 
48330368db7SStefano Zampini   PetscFunctionBegin;
48430368db7SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
48530368db7SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
48630368db7SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
48730368db7SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
48830368db7SStefano Zampini   PetscFunctionReturn(0);
48930368db7SStefano Zampini }
4902d505d7fSStefano Zampini 
4913100ebe3SStefano Zampini static PetscErrorCode PCBDDCGetPrimalVerticesIS_BDDC(PC pc, IS *is)
4923100ebe3SStefano Zampini {
4933100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC*)pc->data;
4943100ebe3SStefano Zampini 
4953100ebe3SStefano Zampini   PetscFunctionBegin;
4963100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices;
4973100ebe3SStefano Zampini   PetscFunctionReturn(0);
4983100ebe3SStefano Zampini }
4993100ebe3SStefano Zampini 
5003100ebe3SStefano Zampini /*@
5013100ebe3SStefano Zampini  PCBDDCGetPrimalVerticesIS - Get user defined primal vertices set with PCBDDCSetPrimalVerticesIS()
5023100ebe3SStefano Zampini 
5033100ebe3SStefano Zampini    Collective
5043100ebe3SStefano Zampini 
5053100ebe3SStefano Zampini    Input Parameters:
5063100ebe3SStefano Zampini .  pc - the preconditioning context
5073100ebe3SStefano Zampini 
5083100ebe3SStefano Zampini    Output Parameters:
5093100ebe3SStefano Zampini .  is - index set of primal vertices in global numbering (NULL if not set)
5103100ebe3SStefano Zampini 
5113100ebe3SStefano Zampini    Level: intermediate
5123100ebe3SStefano Zampini 
5133100ebe3SStefano Zampini    Notes:
5143100ebe3SStefano Zampini 
5153100ebe3SStefano Zampini .seealso: PCBDDC, PCBDDCSetPrimalVerticesIS(), PCBDDCSetPrimalVerticesLocalIS(), PCBDDCGetPrimalVerticesLocalIS()
5163100ebe3SStefano Zampini @*/
5173100ebe3SStefano Zampini PetscErrorCode PCBDDCGetPrimalVerticesIS(PC pc, IS *is)
5183100ebe3SStefano Zampini {
5193100ebe3SStefano Zampini   PetscErrorCode ierr;
5203100ebe3SStefano Zampini 
5213100ebe3SStefano Zampini   PetscFunctionBegin;
5223100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5233100ebe3SStefano Zampini   PetscValidPointer(is,2);
5243100ebe3SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetPrimalVerticesIS_C",(PC,IS*),(pc,is));CHKERRQ(ierr);
5253100ebe3SStefano Zampini   PetscFunctionReturn(0);
5263100ebe3SStefano Zampini }
5273100ebe3SStefano Zampini 
528674ae819SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
529674ae819SStefano Zampini {
530674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
53156282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
532674ae819SStefano Zampini   PetscErrorCode ierr;
5331e6b0712SBarry Smith 
534674ae819SStefano Zampini   PetscFunctionBegin;
53556282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
53656282151SStefano Zampini   if (pcbddc->user_primal_vertices_local) {
53756282151SStefano Zampini     ierr = ISEqual(PrimalVertices,pcbddc->user_primal_vertices_local,&isequal);CHKERRQ(ierr);
53856282151SStefano Zampini   }
539674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
54030368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
54130368db7SStefano Zampini   pcbddc->user_primal_vertices_local = PrimalVertices;
54256282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
543674ae819SStefano Zampini   PetscFunctionReturn(0);
544674ae819SStefano Zampini }
5453100ebe3SStefano Zampini 
546674ae819SStefano Zampini /*@
54728509bceSStefano Zampini  PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in PCBDDC
548674ae819SStefano Zampini 
54917eb1463SStefano Zampini    Collective
550674ae819SStefano Zampini 
551674ae819SStefano Zampini    Input Parameters:
552674ae819SStefano Zampini +  pc - the preconditioning context
55317eb1463SStefano Zampini -  PrimalVertices - index set of primal vertices in local numbering (can be empty)
554674ae819SStefano Zampini 
555674ae819SStefano Zampini    Level: intermediate
556674ae819SStefano Zampini 
557674ae819SStefano Zampini    Notes:
558674ae819SStefano Zampini 
5593100ebe3SStefano Zampini .seealso: PCBDDC, PCBDDCSetPrimalVerticesIS(), PCBDDCGetPrimalVerticesIS(), PCBDDCGetPrimalVerticesLocalIS()
560674ae819SStefano Zampini @*/
561674ae819SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
562674ae819SStefano Zampini {
563674ae819SStefano Zampini   PetscErrorCode ierr;
564674ae819SStefano Zampini 
565674ae819SStefano Zampini   PetscFunctionBegin;
566674ae819SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
567674ae819SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
56817eb1463SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
569674ae819SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
570674ae819SStefano Zampini   PetscFunctionReturn(0);
571674ae819SStefano Zampini }
5722d505d7fSStefano Zampini 
5733100ebe3SStefano Zampini static PetscErrorCode PCBDDCGetPrimalVerticesLocalIS_BDDC(PC pc, IS *is)
5743100ebe3SStefano Zampini {
5753100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC*)pc->data;
5763100ebe3SStefano Zampini 
5773100ebe3SStefano Zampini   PetscFunctionBegin;
5783100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices_local;
5793100ebe3SStefano Zampini   PetscFunctionReturn(0);
5803100ebe3SStefano Zampini }
5813100ebe3SStefano Zampini 
5823100ebe3SStefano Zampini /*@
5833100ebe3SStefano Zampini  PCBDDCGetPrimalVerticesLocalIS - Get user defined primal vertices set with PCBDDCSetPrimalVerticesLocalIS()
5843100ebe3SStefano Zampini 
5853100ebe3SStefano Zampini    Collective
5863100ebe3SStefano Zampini 
5873100ebe3SStefano Zampini    Input Parameters:
5883100ebe3SStefano Zampini .  pc - the preconditioning context
5893100ebe3SStefano Zampini 
5903100ebe3SStefano Zampini    Output Parameters:
5913100ebe3SStefano Zampini .  is - index set of primal vertices in local numbering (NULL if not set)
5923100ebe3SStefano Zampini 
5933100ebe3SStefano Zampini    Level: intermediate
5943100ebe3SStefano Zampini 
5953100ebe3SStefano Zampini    Notes:
5963100ebe3SStefano Zampini 
5973100ebe3SStefano Zampini .seealso: PCBDDC, PCBDDCSetPrimalVerticesIS(), PCBDDCGetPrimalVerticesIS(), PCBDDCSetPrimalVerticesLocalIS()
5983100ebe3SStefano Zampini @*/
5993100ebe3SStefano Zampini PetscErrorCode PCBDDCGetPrimalVerticesLocalIS(PC pc, IS *is)
6003100ebe3SStefano Zampini {
6013100ebe3SStefano Zampini   PetscErrorCode ierr;
6023100ebe3SStefano Zampini 
6033100ebe3SStefano Zampini   PetscFunctionBegin;
6043100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
6053100ebe3SStefano Zampini   PetscValidPointer(is,2);
6063100ebe3SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetPrimalVerticesLocalIS_C",(PC,IS*),(pc,is));CHKERRQ(ierr);
6073100ebe3SStefano Zampini   PetscFunctionReturn(0);
6083100ebe3SStefano Zampini }
6093100ebe3SStefano Zampini 
6104fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k)
6114fad6a16SStefano Zampini {
6124fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
6134fad6a16SStefano Zampini 
6144fad6a16SStefano Zampini   PetscFunctionBegin;
6154fad6a16SStefano Zampini   pcbddc->coarsening_ratio = k;
6164fad6a16SStefano Zampini   PetscFunctionReturn(0);
6174fad6a16SStefano Zampini }
6181e6b0712SBarry Smith 
6194fad6a16SStefano Zampini /*@
62028509bceSStefano Zampini  PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel
6214fad6a16SStefano Zampini 
6224fad6a16SStefano Zampini    Logically collective on PC
6234fad6a16SStefano Zampini 
6244fad6a16SStefano Zampini    Input Parameters:
6254fad6a16SStefano Zampini +  pc - the preconditioning context
62628509bceSStefano Zampini -  k - coarsening ratio (H/h at the coarser level)
6274fad6a16SStefano Zampini 
6280f202f7eSStefano Zampini    Options Database Keys:
6290f202f7eSStefano Zampini .    -pc_bddc_coarsening_ratio
6304fad6a16SStefano Zampini 
6314fad6a16SStefano Zampini    Level: intermediate
6324fad6a16SStefano Zampini 
6334fad6a16SStefano Zampini    Notes:
6340f202f7eSStefano Zampini      Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level
6354fad6a16SStefano Zampini 
6360f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetLevels()
6374fad6a16SStefano Zampini @*/
6384fad6a16SStefano Zampini PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k)
6394fad6a16SStefano Zampini {
6404fad6a16SStefano Zampini   PetscErrorCode ierr;
6414fad6a16SStefano Zampini 
6424fad6a16SStefano Zampini   PetscFunctionBegin;
6434fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
6442b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,k,2);
6454fad6a16SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));CHKERRQ(ierr);
6464fad6a16SStefano Zampini   PetscFunctionReturn(0);
6474fad6a16SStefano Zampini }
6482b510759SStefano Zampini 
649b8ffe317SStefano Zampini /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */
650b8ffe317SStefano Zampini static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc,PetscBool flg)
651b8ffe317SStefano Zampini {
652b8ffe317SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
653b8ffe317SStefano Zampini 
654b8ffe317SStefano Zampini   PetscFunctionBegin;
65585c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = flg;
656b8ffe317SStefano Zampini   PetscFunctionReturn(0);
657b8ffe317SStefano Zampini }
658b8ffe317SStefano Zampini 
659b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool flg)
6602b510759SStefano Zampini {
6612b510759SStefano Zampini   PetscErrorCode ierr;
6622b510759SStefano Zampini 
6632b510759SStefano Zampini   PetscFunctionBegin;
6642b510759SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
665b8ffe317SStefano Zampini   PetscValidLogicalCollectiveBool(pc,flg,2);
666b8ffe317SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetUseExactDirichlet_C",(PC,PetscBool),(pc,flg));CHKERRQ(ierr);
6672b510759SStefano Zampini   PetscFunctionReturn(0);
6682b510759SStefano Zampini }
6691e6b0712SBarry Smith 
6702b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc,PetscInt level)
6714fad6a16SStefano Zampini {
6724fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
6734fad6a16SStefano Zampini 
6744fad6a16SStefano Zampini   PetscFunctionBegin;
6752b510759SStefano Zampini   pcbddc->current_level = level;
6764fad6a16SStefano Zampini   PetscFunctionReturn(0);
6774fad6a16SStefano Zampini }
6781e6b0712SBarry Smith 
679b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level)
680b8ffe317SStefano Zampini {
681b8ffe317SStefano Zampini   PetscErrorCode ierr;
682b8ffe317SStefano Zampini 
683b8ffe317SStefano Zampini   PetscFunctionBegin;
684b8ffe317SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
685b8ffe317SStefano Zampini   PetscValidLogicalCollectiveInt(pc,level,2);
686b8ffe317SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLevel_C",(PC,PetscInt),(pc,level));CHKERRQ(ierr);
687b8ffe317SStefano Zampini   PetscFunctionReturn(0);
688b8ffe317SStefano Zampini }
689b8ffe317SStefano Zampini 
6902b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc,PetscInt levels)
6912b510759SStefano Zampini {
6922b510759SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
6932b510759SStefano Zampini 
6942b510759SStefano Zampini   PetscFunctionBegin;
6956080607fSStefano Zampini   if (levels > PETSC_PCBDDC_MAXLEVELS-1) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Maximum number of additional levels for BDDC is %d",PETSC_PCBDDC_MAXLEVELS-1);
6962b510759SStefano Zampini   pcbddc->max_levels = levels;
6972b510759SStefano Zampini   PetscFunctionReturn(0);
6982b510759SStefano Zampini }
6992b510759SStefano Zampini 
7004fad6a16SStefano Zampini /*@
70137ebbdf7SStefano Zampini  PCBDDCSetLevels - Sets the maximum number of additional levels allowed for multilevel BDDC
7024fad6a16SStefano Zampini 
7034fad6a16SStefano Zampini    Logically collective on PC
7044fad6a16SStefano Zampini 
7054fad6a16SStefano Zampini    Input Parameters:
7064fad6a16SStefano Zampini +  pc - the preconditioning context
70737ebbdf7SStefano Zampini -  levels - the maximum number of levels
7084fad6a16SStefano Zampini 
7090f202f7eSStefano Zampini    Options Database Keys:
7100f202f7eSStefano Zampini .    -pc_bddc_levels
7114fad6a16SStefano Zampini 
7124fad6a16SStefano Zampini    Level: intermediate
7134fad6a16SStefano Zampini 
7144fad6a16SStefano Zampini    Notes:
71537ebbdf7SStefano Zampini      The default value is 0, that gives the classical two-levels BDDC
7164fad6a16SStefano Zampini 
7170f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetCoarseningRatio()
7184fad6a16SStefano Zampini @*/
7192b510759SStefano Zampini PetscErrorCode PCBDDCSetLevels(PC pc,PetscInt levels)
7204fad6a16SStefano Zampini {
7214fad6a16SStefano Zampini   PetscErrorCode ierr;
7224fad6a16SStefano Zampini 
7234fad6a16SStefano Zampini   PetscFunctionBegin;
7244fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
7252b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,levels,2);
7262b510759SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLevels_C",(PC,PetscInt),(pc,levels));CHKERRQ(ierr);
7274fad6a16SStefano Zampini   PetscFunctionReturn(0);
7284fad6a16SStefano Zampini }
7291e6b0712SBarry Smith 
7303b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
7313b03a366Sstefano_zampini {
7323b03a366Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
73356282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
7343b03a366Sstefano_zampini   PetscErrorCode ierr;
7353b03a366Sstefano_zampini 
7363b03a366Sstefano_zampini   PetscFunctionBegin;
73756282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
73856282151SStefano Zampini   if (pcbddc->DirichletBoundaries) {
73956282151SStefano Zampini     ierr = ISEqual(DirichletBoundaries,pcbddc->DirichletBoundaries,&isequal);CHKERRQ(ierr);
74056282151SStefano Zampini   }
741785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
742785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
7433b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
74436e030ebSStefano Zampini   pcbddc->DirichletBoundaries = DirichletBoundaries;
74556282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7463b03a366Sstefano_zampini   PetscFunctionReturn(0);
7473b03a366Sstefano_zampini }
7481e6b0712SBarry Smith 
7493b03a366Sstefano_zampini /*@
75028509bceSStefano Zampini  PCBDDCSetDirichletBoundaries - Set IS defining Dirichlet boundaries for the global problem.
7513b03a366Sstefano_zampini 
752785d1243SStefano Zampini    Collective
7533b03a366Sstefano_zampini 
7543b03a366Sstefano_zampini    Input Parameters:
7553b03a366Sstefano_zampini +  pc - the preconditioning context
756785d1243SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries
7573b03a366Sstefano_zampini 
7583b03a366Sstefano_zampini    Level: intermediate
7593b03a366Sstefano_zampini 
7600f202f7eSStefano Zampini    Notes:
7610f202f7eSStefano Zampini      Provide the information if you used MatZeroRows/Columns routines. Any process can list any global node
7623b03a366Sstefano_zampini 
7630f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetDirichletBoundariesLocal(), MatZeroRows(), MatZeroRowsColumns()
7643b03a366Sstefano_zampini @*/
7653b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
7663b03a366Sstefano_zampini {
7673b03a366Sstefano_zampini   PetscErrorCode ierr;
7683b03a366Sstefano_zampini 
7693b03a366Sstefano_zampini   PetscFunctionBegin;
7703b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
771674ae819SStefano Zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
772785d1243SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
7733b03a366Sstefano_zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
7743b03a366Sstefano_zampini   PetscFunctionReturn(0);
7753b03a366Sstefano_zampini }
7761e6b0712SBarry Smith 
77782ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc,IS DirichletBoundaries)
7783b03a366Sstefano_zampini {
7793b03a366Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
78056282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
7813b03a366Sstefano_zampini   PetscErrorCode ierr;
7823b03a366Sstefano_zampini 
7833b03a366Sstefano_zampini   PetscFunctionBegin;
78456282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
78556282151SStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
78656282151SStefano Zampini     ierr = ISEqual(DirichletBoundaries,pcbddc->DirichletBoundariesLocal,&isequal);CHKERRQ(ierr);
78756282151SStefano Zampini   }
788785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
789785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
7903b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
791785d1243SStefano Zampini   pcbddc->DirichletBoundariesLocal = DirichletBoundaries;
79256282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7933b03a366Sstefano_zampini   PetscFunctionReturn(0);
7943b03a366Sstefano_zampini }
7953b03a366Sstefano_zampini 
7963b03a366Sstefano_zampini /*@
79782ba6b80SStefano Zampini  PCBDDCSetDirichletBoundariesLocal - Set IS defining Dirichlet boundaries for the global problem in local ordering.
7983b03a366Sstefano_zampini 
799785d1243SStefano Zampini    Collective
8003b03a366Sstefano_zampini 
8013b03a366Sstefano_zampini    Input Parameters:
8023b03a366Sstefano_zampini +  pc - the preconditioning context
80382ba6b80SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries (in local ordering)
8043b03a366Sstefano_zampini 
8053b03a366Sstefano_zampini    Level: intermediate
8063b03a366Sstefano_zampini 
8073b03a366Sstefano_zampini    Notes:
8083b03a366Sstefano_zampini 
8090f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetDirichletBoundaries(), MatZeroRows(), MatZeroRowsColumns()
8103b03a366Sstefano_zampini @*/
81182ba6b80SStefano Zampini PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc,IS DirichletBoundaries)
8123b03a366Sstefano_zampini {
8133b03a366Sstefano_zampini   PetscErrorCode ierr;
8143b03a366Sstefano_zampini 
8153b03a366Sstefano_zampini   PetscFunctionBegin;
8163b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
8173b03a366Sstefano_zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
81882ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
81982ba6b80SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundariesLocal_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
8203b03a366Sstefano_zampini   PetscFunctionReturn(0);
8213b03a366Sstefano_zampini }
8223b03a366Sstefano_zampini 
82353cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
8240c7d97c5SJed Brown {
8250c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
82656282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
82753cdbc3dSStefano Zampini   PetscErrorCode ierr;
8280c7d97c5SJed Brown 
8290c7d97c5SJed Brown   PetscFunctionBegin;
83056282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
83156282151SStefano Zampini   if (pcbddc->NeumannBoundaries) {
83256282151SStefano Zampini     ierr = ISEqual(NeumannBoundaries,pcbddc->NeumannBoundaries,&isequal);CHKERRQ(ierr);
83356282151SStefano Zampini   }
834785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
835785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
83653cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
83736e030ebSStefano Zampini   pcbddc->NeumannBoundaries = NeumannBoundaries;
83856282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
8390c7d97c5SJed Brown   PetscFunctionReturn(0);
8400c7d97c5SJed Brown }
8411e6b0712SBarry Smith 
84257527edcSJed Brown /*@
84328509bceSStefano Zampini  PCBDDCSetNeumannBoundaries - Set IS defining Neumann boundaries for the global problem.
84457527edcSJed Brown 
845785d1243SStefano Zampini    Collective
84657527edcSJed Brown 
84757527edcSJed Brown    Input Parameters:
84857527edcSJed Brown +  pc - the preconditioning context
849785d1243SStefano Zampini -  NeumannBoundaries - parallel IS defining the Neumann boundaries
85057527edcSJed Brown 
85157527edcSJed Brown    Level: intermediate
85257527edcSJed Brown 
8530f202f7eSStefano Zampini    Notes:
8540f202f7eSStefano Zampini      Any process can list any global node
85557527edcSJed Brown 
8560f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetNeumannBoundariesLocal()
85757527edcSJed Brown @*/
85853cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
8590c7d97c5SJed Brown {
8600c7d97c5SJed Brown   PetscErrorCode ierr;
8610c7d97c5SJed Brown 
8620c7d97c5SJed Brown   PetscFunctionBegin;
8630c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
864674ae819SStefano Zampini   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
865785d1243SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
86653cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
86753cdbc3dSStefano Zampini   PetscFunctionReturn(0);
86853cdbc3dSStefano Zampini }
8691e6b0712SBarry Smith 
87082ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc,IS NeumannBoundaries)
8710c7d97c5SJed Brown {
8720c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
87356282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
8740c7d97c5SJed Brown   PetscErrorCode ierr;
8750c7d97c5SJed Brown 
8760c7d97c5SJed Brown   PetscFunctionBegin;
87756282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
87856282151SStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
87956282151SStefano Zampini     ierr = ISEqual(NeumannBoundaries,pcbddc->NeumannBoundariesLocal,&isequal);CHKERRQ(ierr);
88056282151SStefano Zampini   }
881785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
882785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
8830c7d97c5SJed Brown   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
884785d1243SStefano Zampini   pcbddc->NeumannBoundariesLocal = NeumannBoundaries;
88556282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
8860c7d97c5SJed Brown   PetscFunctionReturn(0);
8870c7d97c5SJed Brown }
8880c7d97c5SJed Brown 
8890c7d97c5SJed Brown /*@
89082ba6b80SStefano Zampini  PCBDDCSetNeumannBoundariesLocal - Set IS defining Neumann boundaries for the global problem in local ordering.
8910c7d97c5SJed Brown 
892785d1243SStefano Zampini    Collective
8930c7d97c5SJed Brown 
8940c7d97c5SJed Brown    Input Parameters:
8950c7d97c5SJed Brown +  pc - the preconditioning context
89682ba6b80SStefano Zampini -  NeumannBoundaries - parallel IS defining the subdomain part of Neumann boundaries (in local ordering)
8970c7d97c5SJed Brown 
8980c7d97c5SJed Brown    Level: intermediate
8990c7d97c5SJed Brown 
9000c7d97c5SJed Brown    Notes:
9010c7d97c5SJed Brown 
9020f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetNeumannBoundaries()
9030c7d97c5SJed Brown @*/
90482ba6b80SStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc,IS NeumannBoundaries)
9050c7d97c5SJed Brown {
9060c7d97c5SJed Brown   PetscErrorCode ierr;
9070c7d97c5SJed Brown 
9080c7d97c5SJed Brown   PetscFunctionBegin;
9090c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
9100c7d97c5SJed Brown   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
91182ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
91282ba6b80SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundariesLocal_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
91353cdbc3dSStefano Zampini   PetscFunctionReturn(0);
91453cdbc3dSStefano Zampini }
91553cdbc3dSStefano Zampini 
916da1bb401SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
917da1bb401SStefano Zampini {
918da1bb401SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
919da1bb401SStefano Zampini 
920da1bb401SStefano Zampini   PetscFunctionBegin;
921da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
922da1bb401SStefano Zampini   PetscFunctionReturn(0);
923da1bb401SStefano Zampini }
9241e6b0712SBarry Smith 
925da1bb401SStefano Zampini /*@
926785d1243SStefano Zampini  PCBDDCGetDirichletBoundaries - Get parallel IS for Dirichlet boundaries
927da1bb401SStefano Zampini 
928785d1243SStefano Zampini    Collective
929785d1243SStefano Zampini 
930785d1243SStefano Zampini    Input Parameters:
931785d1243SStefano Zampini .  pc - the preconditioning context
932785d1243SStefano Zampini 
933785d1243SStefano Zampini    Output Parameters:
934785d1243SStefano Zampini .  DirichletBoundaries - index set defining the Dirichlet boundaries
935785d1243SStefano Zampini 
936785d1243SStefano Zampini    Level: intermediate
937785d1243SStefano Zampini 
9380f202f7eSStefano Zampini    Notes:
9390f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetDirichletBoundaries
940785d1243SStefano Zampini 
941785d1243SStefano Zampini .seealso: PCBDDC
942785d1243SStefano Zampini @*/
943785d1243SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
944785d1243SStefano Zampini {
945785d1243SStefano Zampini   PetscErrorCode ierr;
946785d1243SStefano Zampini 
947785d1243SStefano Zampini   PetscFunctionBegin;
948785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
949785d1243SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
950785d1243SStefano Zampini   PetscFunctionReturn(0);
951785d1243SStefano Zampini }
952785d1243SStefano Zampini 
953785d1243SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc,IS *DirichletBoundaries)
954785d1243SStefano Zampini {
955785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
956785d1243SStefano Zampini 
957785d1243SStefano Zampini   PetscFunctionBegin;
958785d1243SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundariesLocal;
959785d1243SStefano Zampini   PetscFunctionReturn(0);
960785d1243SStefano Zampini }
961785d1243SStefano Zampini 
962da1bb401SStefano Zampini /*@
96382ba6b80SStefano Zampini  PCBDDCGetDirichletBoundariesLocal - Get parallel IS for Dirichlet boundaries (in local ordering)
964da1bb401SStefano Zampini 
965785d1243SStefano Zampini    Collective
966da1bb401SStefano Zampini 
967da1bb401SStefano Zampini    Input Parameters:
96828509bceSStefano Zampini .  pc - the preconditioning context
969da1bb401SStefano Zampini 
970da1bb401SStefano Zampini    Output Parameters:
97128509bceSStefano Zampini .  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
972da1bb401SStefano Zampini 
973da1bb401SStefano Zampini    Level: intermediate
974da1bb401SStefano Zampini 
975da1bb401SStefano Zampini    Notes:
9760f202f7eSStefano 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).
9770f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
978da1bb401SStefano Zampini 
979da1bb401SStefano Zampini .seealso: PCBDDC
980da1bb401SStefano Zampini @*/
98182ba6b80SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc,IS *DirichletBoundaries)
982da1bb401SStefano Zampini {
983da1bb401SStefano Zampini   PetscErrorCode ierr;
984da1bb401SStefano Zampini 
985da1bb401SStefano Zampini   PetscFunctionBegin;
986da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
98782ba6b80SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundariesLocal_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
988da1bb401SStefano Zampini   PetscFunctionReturn(0);
989da1bb401SStefano Zampini }
9901e6b0712SBarry Smith 
99153cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
99253cdbc3dSStefano Zampini {
99353cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
99453cdbc3dSStefano Zampini 
99553cdbc3dSStefano Zampini   PetscFunctionBegin;
99653cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
99753cdbc3dSStefano Zampini   PetscFunctionReturn(0);
99853cdbc3dSStefano Zampini }
9991e6b0712SBarry Smith 
100053cdbc3dSStefano Zampini /*@
1001785d1243SStefano Zampini  PCBDDCGetNeumannBoundaries - Get parallel IS for Neumann boundaries
100253cdbc3dSStefano Zampini 
1003785d1243SStefano Zampini    Collective
1004785d1243SStefano Zampini 
1005785d1243SStefano Zampini    Input Parameters:
1006785d1243SStefano Zampini .  pc - the preconditioning context
1007785d1243SStefano Zampini 
1008785d1243SStefano Zampini    Output Parameters:
1009785d1243SStefano Zampini .  NeumannBoundaries - index set defining the Neumann boundaries
1010785d1243SStefano Zampini 
1011785d1243SStefano Zampini    Level: intermediate
1012785d1243SStefano Zampini 
10130f202f7eSStefano Zampini    Notes:
10140f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetNeumannBoundaries
1015785d1243SStefano Zampini 
1016785d1243SStefano Zampini .seealso: PCBDDC
1017785d1243SStefano Zampini @*/
1018785d1243SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
1019785d1243SStefano Zampini {
1020785d1243SStefano Zampini   PetscErrorCode ierr;
1021785d1243SStefano Zampini 
1022785d1243SStefano Zampini   PetscFunctionBegin;
1023785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1024785d1243SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
1025785d1243SStefano Zampini   PetscFunctionReturn(0);
1026785d1243SStefano Zampini }
1027785d1243SStefano Zampini 
1028785d1243SStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc,IS *NeumannBoundaries)
1029785d1243SStefano Zampini {
1030785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1031785d1243SStefano Zampini 
1032785d1243SStefano Zampini   PetscFunctionBegin;
1033785d1243SStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundariesLocal;
1034785d1243SStefano Zampini   PetscFunctionReturn(0);
1035785d1243SStefano Zampini }
1036785d1243SStefano Zampini 
103753cdbc3dSStefano Zampini /*@
103882ba6b80SStefano Zampini  PCBDDCGetNeumannBoundariesLocal - Get parallel IS for Neumann boundaries (in local ordering)
103953cdbc3dSStefano Zampini 
1040785d1243SStefano Zampini    Collective
104153cdbc3dSStefano Zampini 
104253cdbc3dSStefano Zampini    Input Parameters:
104328509bceSStefano Zampini .  pc - the preconditioning context
104453cdbc3dSStefano Zampini 
104553cdbc3dSStefano Zampini    Output Parameters:
104628509bceSStefano Zampini .  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
104753cdbc3dSStefano Zampini 
104853cdbc3dSStefano Zampini    Level: intermediate
104953cdbc3dSStefano Zampini 
105053cdbc3dSStefano Zampini    Notes:
10510f202f7eSStefano 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).
10520f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
105353cdbc3dSStefano Zampini 
105453cdbc3dSStefano Zampini .seealso: PCBDDC
105553cdbc3dSStefano Zampini @*/
105682ba6b80SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc,IS *NeumannBoundaries)
105753cdbc3dSStefano Zampini {
105853cdbc3dSStefano Zampini   PetscErrorCode ierr;
105953cdbc3dSStefano Zampini 
106053cdbc3dSStefano Zampini   PetscFunctionBegin;
106153cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
106282ba6b80SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundariesLocal_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
10630c7d97c5SJed Brown   PetscFunctionReturn(0);
10640c7d97c5SJed Brown }
10651e6b0712SBarry Smith 
10661a83f524SJed Brown static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
106736e030ebSStefano Zampini {
106836e030ebSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1069da1bb401SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
107056282151SStefano Zampini   PetscBool      same_data = PETSC_FALSE;
1071da1bb401SStefano Zampini   PetscErrorCode ierr;
107236e030ebSStefano Zampini 
107336e030ebSStefano Zampini   PetscFunctionBegin;
10748687889aSStefano Zampini   if (!nvtxs) {
107504194a47SStefano Zampini     if (copymode == PETSC_OWN_POINTER) {
107604194a47SStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
107704194a47SStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
107804194a47SStefano Zampini     }
10798687889aSStefano Zampini     ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
10808687889aSStefano Zampini     PetscFunctionReturn(0);
10818687889aSStefano Zampini   }
108266da6bd7Sstefano_zampini   if (mat_graph->nvtxs == nvtxs && mat_graph->freecsr) { /* we own the data */
108356282151SStefano Zampini     if (mat_graph->xadj == xadj && mat_graph->adjncy == adjncy) same_data = PETSC_TRUE;
108456282151SStefano Zampini     if (!same_data && mat_graph->xadj[nvtxs] == xadj[nvtxs]) {
1085580bdb30SBarry Smith       ierr = PetscArraycmp(xadj,mat_graph->xadj,nvtxs+1,&same_data);CHKERRQ(ierr);
10862d505d7fSStefano Zampini       if (same_data) {
1087580bdb30SBarry Smith         ierr = PetscArraycmp(adjncy,mat_graph->adjncy,xadj[nvtxs],&same_data);CHKERRQ(ierr);
10882d505d7fSStefano Zampini       }
108956282151SStefano Zampini     }
109056282151SStefano Zampini   }
109156282151SStefano Zampini   if (!same_data) {
1092674ae819SStefano Zampini     /* free old CSR */
1093674ae819SStefano Zampini     ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
1094674ae819SStefano Zampini     /* get CSR into graph structure */
1095da1bb401SStefano Zampini     if (copymode == PETSC_COPY_VALUES) {
1096854ce69bSBarry Smith       ierr = PetscMalloc1(nvtxs+1,&mat_graph->xadj);CHKERRQ(ierr);
1097785e854fSJed Brown       ierr = PetscMalloc1(xadj[nvtxs],&mat_graph->adjncy);CHKERRQ(ierr);
1098580bdb30SBarry Smith       ierr = PetscArraycpy(mat_graph->xadj,xadj,nvtxs+1);CHKERRQ(ierr);
1099580bdb30SBarry Smith       ierr = PetscArraycpy(mat_graph->adjncy,adjncy,xadj[nvtxs]);CHKERRQ(ierr);
1100a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1101da1bb401SStefano Zampini     } else if (copymode == PETSC_OWN_POINTER) {
11021a83f524SJed Brown       mat_graph->xadj    = (PetscInt*)xadj;
11031a83f524SJed Brown       mat_graph->adjncy  = (PetscInt*)adjncy;
1104a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1105a1dbd327SStefano Zampini     } else if (copymode == PETSC_USE_POINTER) {
1106a1dbd327SStefano Zampini       mat_graph->xadj    = (PetscInt*)xadj;
1107a1dbd327SStefano Zampini       mat_graph->adjncy  = (PetscInt*)adjncy;
1108a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_FALSE;
1109e0fe2d75SToby Isaac     } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %D",copymode);
1110575ad6abSStefano Zampini     mat_graph->nvtxs_csr = nvtxs;
111156282151SStefano Zampini     pcbddc->recompute_topography = PETSC_TRUE;
111256282151SStefano Zampini   }
111336e030ebSStefano Zampini   PetscFunctionReturn(0);
111436e030ebSStefano Zampini }
11151e6b0712SBarry Smith 
111636e030ebSStefano Zampini /*@
111754fffbccSStefano Zampini  PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local degrees of freedom.
111836e030ebSStefano Zampini 
111936e030ebSStefano Zampini    Not collective
112036e030ebSStefano Zampini 
112136e030ebSStefano Zampini    Input Parameters:
112254fffbccSStefano Zampini +  pc - the preconditioning context.
112354fffbccSStefano Zampini .  nvtxs - number of local vertices of the graph (i.e., the number of local dofs).
112454fffbccSStefano Zampini .  xadj, adjncy - the connectivity of the dofs in CSR format.
112554fffbccSStefano Zampini -  copymode - supported modes are PETSC_COPY_VALUES, PETSC_USE_POINTER or PETSC_OWN_POINTER.
112636e030ebSStefano Zampini 
112736e030ebSStefano Zampini    Level: intermediate
112836e030ebSStefano Zampini 
112995452b02SPatrick Sanan    Notes:
113095452b02SPatrick Sanan     A dof is considered connected with all local dofs if xadj[dof+1]-xadj[dof] == 1 and adjncy[xadj[dof]] is negative.
113136e030ebSStefano Zampini 
113228509bceSStefano Zampini .seealso: PCBDDC,PetscCopyMode
113336e030ebSStefano Zampini @*/
11341a83f524SJed Brown PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
113536e030ebSStefano Zampini {
1136575ad6abSStefano Zampini   void (*f)(void) = 0;
113736e030ebSStefano Zampini   PetscErrorCode ierr;
113836e030ebSStefano Zampini 
113936e030ebSStefano Zampini   PetscFunctionBegin;
114036e030ebSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
11418687889aSStefano Zampini   if (nvtxs) {
1142674ae819SStefano Zampini     PetscValidIntPointer(xadj,3);
11431633d1f0SStefano Zampini     if (xadj[nvtxs]) PetscValidIntPointer(adjncy,4);
11448687889aSStefano Zampini   }
11451a83f524SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
1146575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
1147575ad6abSStefano Zampini   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr);
1148575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
1149575ad6abSStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
1150575ad6abSStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
1151da1bb401SStefano Zampini   }
115236e030ebSStefano Zampini   PetscFunctionReturn(0);
115336e030ebSStefano Zampini }
11541e6b0712SBarry Smith 
115563602bcaSStefano Zampini static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
115663602bcaSStefano Zampini {
115763602bcaSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
115863602bcaSStefano Zampini   PetscInt       i;
115956282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
116063602bcaSStefano Zampini   PetscErrorCode ierr;
116163602bcaSStefano Zampini 
116263602bcaSStefano Zampini   PetscFunctionBegin;
116356282151SStefano Zampini   if (pcbddc->n_ISForDofsLocal == n_is) {
116456282151SStefano Zampini     for (i=0;i<n_is;i++) {
116556282151SStefano Zampini       PetscBool isequalt;
116656282151SStefano Zampini       ierr = ISEqual(ISForDofs[i],pcbddc->ISForDofsLocal[i],&isequalt);CHKERRQ(ierr);
116756282151SStefano Zampini       if (!isequalt) break;
116856282151SStefano Zampini     }
116956282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
117056282151SStefano Zampini   }
117156282151SStefano Zampini   for (i=0;i<n_is;i++) {
117256282151SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
117356282151SStefano Zampini   }
117463602bcaSStefano Zampini   /* Destroy ISes if they were already set */
117563602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
117663602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
117763602bcaSStefano Zampini   }
117863602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
117963602bcaSStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
118063602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
118163602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
118263602bcaSStefano Zampini   }
118363602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
118463602bcaSStefano Zampini   pcbddc->n_ISForDofs = 0;
118563602bcaSStefano Zampini   /* allocate space then set */
1186d02579f5SStefano Zampini   if (n_is) {
1187d02579f5SStefano Zampini     ierr = PetscMalloc1(n_is,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
1188d02579f5SStefano Zampini   }
118963602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
119063602bcaSStefano Zampini     pcbddc->ISForDofsLocal[i] = ISForDofs[i];
119163602bcaSStefano Zampini   }
119263602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = n_is;
119363602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
119456282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
119563602bcaSStefano Zampini   PetscFunctionReturn(0);
119663602bcaSStefano Zampini }
119763602bcaSStefano Zampini 
119863602bcaSStefano Zampini /*@
119963602bcaSStefano Zampini  PCBDDCSetDofsSplittingLocal - Set index sets defining fields of the local subdomain matrix
120063602bcaSStefano Zampini 
120163602bcaSStefano Zampini    Collective
120263602bcaSStefano Zampini 
120363602bcaSStefano Zampini    Input Parameters:
120463602bcaSStefano Zampini +  pc - the preconditioning context
12050f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
12060f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in local ordering
120763602bcaSStefano Zampini 
120863602bcaSStefano Zampini    Level: intermediate
120963602bcaSStefano Zampini 
12100f202f7eSStefano Zampini    Notes:
12110f202f7eSStefano Zampini      n_is should be the same among processes. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
121263602bcaSStefano Zampini 
121363602bcaSStefano Zampini .seealso: PCBDDC
121463602bcaSStefano Zampini @*/
121563602bcaSStefano Zampini PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc,PetscInt n_is, IS ISForDofs[])
121663602bcaSStefano Zampini {
121763602bcaSStefano Zampini   PetscInt       i;
121863602bcaSStefano Zampini   PetscErrorCode ierr;
121963602bcaSStefano Zampini 
122063602bcaSStefano Zampini   PetscFunctionBegin;
122163602bcaSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
122263602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
122363602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
122463602bcaSStefano Zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
122563602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
122663602bcaSStefano Zampini   }
1227e71e7a71SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplittingLocal_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
122863602bcaSStefano Zampini   PetscFunctionReturn(0);
122963602bcaSStefano Zampini }
123063602bcaSStefano Zampini 
12319c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
12329c0446d6SStefano Zampini {
12339c0446d6SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
12349c0446d6SStefano Zampini   PetscInt       i;
123556282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
12369c0446d6SStefano Zampini   PetscErrorCode ierr;
12379c0446d6SStefano Zampini 
12389c0446d6SStefano Zampini   PetscFunctionBegin;
123956282151SStefano Zampini   if (pcbddc->n_ISForDofs == n_is) {
124056282151SStefano Zampini     for (i=0;i<n_is;i++) {
124156282151SStefano Zampini       PetscBool isequalt;
124256282151SStefano Zampini       ierr = ISEqual(ISForDofs[i],pcbddc->ISForDofs[i],&isequalt);CHKERRQ(ierr);
124356282151SStefano Zampini       if (!isequalt) break;
124456282151SStefano Zampini     }
124556282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
124656282151SStefano Zampini   }
124756282151SStefano Zampini   for (i=0;i<n_is;i++) {
124856282151SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
124956282151SStefano Zampini   }
1250da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
12519c0446d6SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
12529c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
12539c0446d6SStefano Zampini   }
1254d11ae9bbSstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
125563602bcaSStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
125663602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
125763602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
125863602bcaSStefano Zampini   }
125963602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
126063602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = 0;
1261da1bb401SStefano Zampini   /* allocate space then set */
1262d02579f5SStefano Zampini   if (n_is) {
1263785e854fSJed Brown     ierr = PetscMalloc1(n_is,&pcbddc->ISForDofs);CHKERRQ(ierr);
1264d02579f5SStefano Zampini   }
12659c0446d6SStefano Zampini   for (i=0;i<n_is;i++) {
1266da1bb401SStefano Zampini     pcbddc->ISForDofs[i] = ISForDofs[i];
12679c0446d6SStefano Zampini   }
12689c0446d6SStefano Zampini   pcbddc->n_ISForDofs = n_is;
126963602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
127056282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
12719c0446d6SStefano Zampini   PetscFunctionReturn(0);
12729c0446d6SStefano Zampini }
12731e6b0712SBarry Smith 
12749c0446d6SStefano Zampini /*@
127563602bcaSStefano Zampini  PCBDDCSetDofsSplitting - Set index sets defining fields of the global matrix
12769c0446d6SStefano Zampini 
127763602bcaSStefano Zampini    Collective
12789c0446d6SStefano Zampini 
12799c0446d6SStefano Zampini    Input Parameters:
12809c0446d6SStefano Zampini +  pc - the preconditioning context
12810f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
12820f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in global ordering
12839c0446d6SStefano Zampini 
12849c0446d6SStefano Zampini    Level: intermediate
12859c0446d6SStefano Zampini 
12860f202f7eSStefano Zampini    Notes:
12870f202f7eSStefano Zampini      Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
12889c0446d6SStefano Zampini 
12899c0446d6SStefano Zampini .seealso: PCBDDC
12909c0446d6SStefano Zampini @*/
12919c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
12929c0446d6SStefano Zampini {
12932b510759SStefano Zampini   PetscInt       i;
12949c0446d6SStefano Zampini   PetscErrorCode ierr;
12959c0446d6SStefano Zampini 
12969c0446d6SStefano Zampini   PetscFunctionBegin;
12979c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
129863602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
12992b510759SStefano Zampini   for (i=0;i<n_is;i++) {
130063602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
1301a011d5a7Sstefano_zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
13022b510759SStefano Zampini   }
13039c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
13049c0446d6SStefano Zampini   PetscFunctionReturn(0);
13059c0446d6SStefano Zampini }
1306906d46d4SStefano Zampini 
1307534831adSStefano Zampini /*
1308534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
1309534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
13109c0446d6SStefano Zampini 
1311534831adSStefano Zampini    Input Parameter:
1312534831adSStefano Zampini +  pc - the preconditioner contex
1313534831adSStefano Zampini 
1314534831adSStefano Zampini    Application Interface Routine: PCPreSolve()
1315534831adSStefano Zampini 
1316534831adSStefano Zampini    Notes:
1317534831adSStefano Zampini      The interface routine PCPreSolve() is not usually called directly by
1318534831adSStefano Zampini    the user, but instead is called by KSPSolve().
1319534831adSStefano Zampini */
1320534831adSStefano Zampini static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1321534831adSStefano Zampini {
1322534831adSStefano Zampini   PetscErrorCode ierr;
1323534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1324534831adSStefano Zampini   PC_IS          *pcis = (PC_IS*)(pc->data);
13253972b0daSStefano Zampini   Vec            used_vec;
13264df7a6bfSStefano Zampini   PetscBool      iscg = PETSC_FALSE, save_rhs = PETSC_TRUE, benign_correction_computed;
1327534831adSStefano Zampini 
1328534831adSStefano Zampini   PetscFunctionBegin;
13291f4df5f7SStefano Zampini   /* if we are working with CG, one dirichlet solve can be avoided during Krylov iterations */
133085c4d303SStefano Zampini   if (ksp) {
13314df7a6bfSStefano Zampini     PetscBool isgroppcg, ispipecg, ispipelcg, ispipecgrr;
13324df7a6bfSStefano Zampini 
133385c4d303SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPCG,&iscg);CHKERRQ(ierr);
133427b6a85dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPGROPPCG,&isgroppcg);CHKERRQ(ierr);
133527b6a85dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECG,&ispipecg);CHKERRQ(ierr);
13364df7a6bfSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECG,&ispipelcg);CHKERRQ(ierr);
1337f94e96cbSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECGRR,&ispipecgrr);CHKERRQ(ierr);
13384df7a6bfSStefano Zampini     iscg = (PetscBool)(iscg || isgroppcg || ispipecg || ispipelcg || ispipecgrr);
13393bf6e316SStefano Zampini     if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || !iscg || pc->mat != pc->pmat) {
134085c4d303SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
134185c4d303SStefano Zampini     }
134285c4d303SStefano Zampini   }
13433bf6e316SStefano Zampini   if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || pc->mat != pc->pmat) {
1344fc17d649SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
1345fc17d649SStefano Zampini   }
13461f4df5f7SStefano Zampini 
134785c4d303SStefano Zampini   /* Creates parallel work vectors used in presolve */
134862a6ff1dSStefano Zampini   if (!pcbddc->original_rhs) {
134962a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
135062a6ff1dSStefano Zampini   }
135162a6ff1dSStefano Zampini   if (!pcbddc->temp_solution) {
135262a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr);
135362a6ff1dSStefano Zampini   }
13548d00608fSStefano Zampini 
135527b6a85dSStefano Zampini   pcbddc->temp_solution_used = PETSC_FALSE;
13563972b0daSStefano Zampini   if (x) {
13573972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);
13583972b0daSStefano Zampini     used_vec = x;
13598d00608fSStefano Zampini   } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */
13603972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr);
13613972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
13623972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
136327b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
1364266e20e9SStefano Zampini     ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
1365266e20e9SStefano Zampini     save_rhs = PETSC_FALSE;
1366266e20e9SStefano Zampini     pcbddc->eliminate_dirdofs = PETSC_TRUE;
13673972b0daSStefano Zampini   }
13688efcfb23SStefano Zampini 
13698efcfb23SStefano Zampini   /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */
13703972b0daSStefano Zampini   if (ksp) {
1371a0cb1b98SStefano Zampini     /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */
13728efcfb23SStefano Zampini     ierr = KSPGetInitialGuessNonzero(ksp,&pcbddc->ksp_guess_nonzero);CHKERRQ(ierr);
13738efcfb23SStefano Zampini     if (!pcbddc->ksp_guess_nonzero) {
13743972b0daSStefano Zampini       ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
13753972b0daSStefano Zampini     }
13763972b0daSStefano Zampini   }
13773308cffdSStefano Zampini 
13788d00608fSStefano Zampini   pcbddc->rhs_change = PETSC_FALSE;
13793972b0daSStefano Zampini   /* Take into account zeroed rows -> change rhs and store solution removed */
138070c64980SStefano Zampini   if (rhs && pcbddc->eliminate_dirdofs) {
13813975b054SStefano Zampini     IS dirIS = NULL;
13823975b054SStefano Zampini 
1383a07ea27aSStefano Zampini     /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */
13843975b054SStefano Zampini     ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
13853975b054SStefano Zampini     if (dirIS) {
1386906d46d4SStefano Zampini       Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
1387785d1243SStefano Zampini       PetscInt          dirsize,i,*is_indices;
13882b095fd8SStefano Zampini       PetscScalar       *array_x;
13892b095fd8SStefano Zampini       const PetscScalar *array_diagonal;
1390785d1243SStefano Zampini 
13913972b0daSStefano Zampini       ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr);
13923972b0daSStefano Zampini       ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr);
1393e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1394e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1395e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1396e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
139782ba6b80SStefano Zampini       ierr = ISGetLocalSize(dirIS,&dirsize);CHKERRQ(ierr);
13983972b0daSStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
13992b095fd8SStefano Zampini       ierr = VecGetArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
14003972b0daSStefano Zampini       ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
14012fa5cd67SKarl Rupp       for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
14023972b0daSStefano Zampini       ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
14032b095fd8SStefano Zampini       ierr = VecRestoreArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
14043972b0daSStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
1405e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1406e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
14078d00608fSStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
14081b968477SStefano Zampini       ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
14098efcfb23SStefano Zampini     }
1410a07ea27aSStefano Zampini   }
1411b76ba322SStefano Zampini 
14128efcfb23SStefano Zampini   /* remove the computed solution or the initial guess from the rhs */
14138d00608fSStefano Zampini   if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero) ) {
141427b6a85dSStefano Zampini     /* save the original rhs */
141527b6a85dSStefano Zampini     if (save_rhs) {
141627b6a85dSStefano Zampini       ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
141727b6a85dSStefano Zampini       save_rhs = PETSC_FALSE;
14188d00608fSStefano Zampini     }
14198d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
14203972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
142127b6a85dSStefano Zampini     ierr = MatMultAdd(pc->mat,used_vec,pcbddc->original_rhs,rhs);CHKERRQ(ierr);
14223972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
14238efcfb23SStefano Zampini     ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr);
142427b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
14257acc28cbSStefano Zampini     if (ksp) {
14267acc28cbSStefano Zampini       ierr = KSPSetInitialGuessNonzero(ksp,PETSC_FALSE);CHKERRQ(ierr);
14277acc28cbSStefano Zampini     }
14283308cffdSStefano Zampini   }
14298efcfb23SStefano Zampini   ierr = VecDestroy(&used_vec);CHKERRQ(ierr);
1430b76ba322SStefano Zampini 
1431fc17d649SStefano Zampini   /* compute initial vector in benign space if needed
143227b6a85dSStefano Zampini      and remove non-benign solution from the rhs */
143327b6a85dSStefano Zampini   benign_correction_computed = PETSC_FALSE;
143408af2428SStefano Zampini   if (rhs && pcbddc->benign_compute_correction && (pcbddc->benign_have_null || pcbddc->benign_apply_coarse_only)) {
14351f4df5f7SStefano Zampini     /* compute u^*_h using ideas similar to those in Xuemin Tu's PhD thesis (see Section 4.8.1)
14361f4df5f7SStefano Zampini        Recursively apply BDDC in the multilevel case */
14370369aaf7SStefano Zampini     if (!pcbddc->benign_vec) {
14380369aaf7SStefano Zampini       ierr = VecDuplicate(rhs,&pcbddc->benign_vec);CHKERRQ(ierr);
14390369aaf7SStefano Zampini     }
1440c69e9cc1SStefano Zampini     /* keep applying coarse solver unless we no longer have benign subdomains */
1441c69e9cc1SStefano Zampini     pcbddc->benign_apply_coarse_only = pcbddc->benign_have_null ? PETSC_TRUE : PETSC_FALSE;
144227b6a85dSStefano Zampini     if (!pcbddc->benign_skip_correction) {
14431dd7afcfSStefano Zampini       ierr = PCApply_BDDC(pc,rhs,pcbddc->benign_vec);CHKERRQ(ierr);
14443bca92a6SStefano Zampini       benign_correction_computed = PETSC_TRUE;
14451f4df5f7SStefano Zampini       if (pcbddc->temp_solution_used) {
14461f4df5f7SStefano Zampini         ierr = VecAXPY(pcbddc->temp_solution,1.0,pcbddc->benign_vec);CHKERRQ(ierr);
14471f4df5f7SStefano Zampini       }
14481f4df5f7SStefano Zampini       ierr = VecScale(pcbddc->benign_vec,-1.0);CHKERRQ(ierr);
144927b6a85dSStefano Zampini       /* store the original rhs if not done earlier */
145027b6a85dSStefano Zampini       if (save_rhs) {
145127b6a85dSStefano Zampini         ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
145292e3dcfbSStefano Zampini       }
145327b6a85dSStefano Zampini       if (pcbddc->rhs_change) {
14540369aaf7SStefano Zampini         ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,rhs,rhs);CHKERRQ(ierr);
145527b6a85dSStefano Zampini       } else {
145627b6a85dSStefano Zampini         ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,pcbddc->original_rhs,rhs);CHKERRQ(ierr);
145727b6a85dSStefano Zampini       }
14580369aaf7SStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
145927b6a85dSStefano Zampini     }
146027b6a85dSStefano Zampini     pcbddc->benign_apply_coarse_only = PETSC_FALSE;
14614df7a6bfSStefano Zampini   } else {
14624df7a6bfSStefano Zampini     ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
14630369aaf7SStefano Zampini   }
14642d4c4fecSStefano Zampini 
14652d4c4fecSStefano Zampini   /* dbg output */
1466a198735bSStefano Zampini   if (pcbddc->dbg_flag && benign_correction_computed) {
14671f4df5f7SStefano Zampini     Vec v;
1468c69e9cc1SStefano Zampini 
14691f4df5f7SStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&v);CHKERRQ(ierr);
1470c69e9cc1SStefano Zampini     if (pcbddc->ChangeOfBasisMatrix) {
14711f4df5f7SStefano Zampini       ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,v);CHKERRQ(ierr);
1472c69e9cc1SStefano Zampini     } else {
1473c69e9cc1SStefano Zampini       ierr = VecCopy(rhs,v);CHKERRQ(ierr);
1474c69e9cc1SStefano Zampini     }
14751f4df5f7SStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,v,PETSC_TRUE);CHKERRQ(ierr);
1476e0fe2d75SToby Isaac     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"LEVEL %D: is the correction benign?\n",pcbddc->current_level);CHKERRQ(ierr);
1477c69e9cc1SStefano Zampini     ierr = PetscScalarView(pcbddc->benign_n,pcbddc->benign_p0,pcbddc->dbg_viewer);CHKERRQ(ierr);
1478c69e9cc1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
14791f4df5f7SStefano Zampini     ierr = VecDestroy(&v);CHKERRQ(ierr);
14801f4df5f7SStefano Zampini   }
14810369aaf7SStefano Zampini 
14820369aaf7SStefano Zampini   /* set initial guess if using PCG */
14838ae0ca82SStefano Zampini   pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
14840369aaf7SStefano Zampini   if (x && pcbddc->use_exact_dirichlet_trick) {
14850369aaf7SStefano Zampini     ierr = VecSet(x,0.0);CHKERRQ(ierr);
14861dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
148727b6a85dSStefano Zampini       if (benign_correction_computed) { /* we have already saved the changed rhs */
14888860a134SJunchao Zhang         ierr = VecLockReadPop(pcis->vec1_global);CHKERRQ(ierr);
14891dd7afcfSStefano Zampini       } else {
14901dd7afcfSStefano Zampini         ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,pcis->vec1_global);CHKERRQ(ierr);
14911dd7afcfSStefano Zampini       }
14921dd7afcfSStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14931dd7afcfSStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14941dd7afcfSStefano Zampini     } else {
14950369aaf7SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14960369aaf7SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14971dd7afcfSStefano Zampini     }
14980369aaf7SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1499c0decd05SBarry Smith     ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D);CHKERRQ(ierr);
15001dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
15011dd7afcfSStefano Zampini       ierr = VecSet(pcis->vec1_global,0.);CHKERRQ(ierr);
15021dd7afcfSStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15031dd7afcfSStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15041dd7afcfSStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x);CHKERRQ(ierr);
15051dd7afcfSStefano Zampini     } else {
15060369aaf7SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15070369aaf7SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15081dd7afcfSStefano Zampini     }
15090369aaf7SStefano Zampini     if (ksp) {
15100369aaf7SStefano Zampini       ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
15110369aaf7SStefano Zampini     }
15128ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_TRUE;
1513266e20e9SStefano Zampini   } else if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior && benign_correction_computed && pcbddc->use_exact_dirichlet_trick) {
15148860a134SJunchao Zhang     ierr = VecLockReadPop(pcis->vec1_global);CHKERRQ(ierr);
15150369aaf7SStefano Zampini   }
1516534831adSStefano Zampini   PetscFunctionReturn(0);
1517534831adSStefano Zampini }
1518906d46d4SStefano Zampini 
1519534831adSStefano Zampini /*
1520534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
1521534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
1522534831adSStefano Zampini 
1523534831adSStefano Zampini    Input Parameter:
1524534831adSStefano Zampini +  pc - the preconditioner contex
1525534831adSStefano Zampini 
1526534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
1527534831adSStefano Zampini 
1528534831adSStefano Zampini    Notes:
1529534831adSStefano Zampini      The interface routine PCPostSolve() is not usually called directly by
1530534831adSStefano Zampini      the user, but instead is called by KSPSolve().
1531534831adSStefano Zampini */
1532534831adSStefano Zampini static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1533534831adSStefano Zampini {
1534534831adSStefano Zampini   PetscErrorCode ierr;
1535534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1536534831adSStefano Zampini 
1537534831adSStefano Zampini   PetscFunctionBegin;
15383972b0daSStefano Zampini   /* add solution removed in presolve */
15396bcfc461SStefano Zampini   if (x && pcbddc->rhs_change) {
154027b6a85dSStefano Zampini     if (pcbddc->temp_solution_used) {
15413425bc38SStefano Zampini       ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr);
1542af140850Sstefano_zampini     } else if (pcbddc->benign_compute_correction && pcbddc->benign_vec) {
154327b6a85dSStefano Zampini       ierr = VecAXPY(x,-1.0,pcbddc->benign_vec);CHKERRQ(ierr);
15443425bc38SStefano Zampini     }
1545af140850Sstefano_zampini     /* restore to original state (not for FETI-DP) */
1546af140850Sstefano_zampini     if (ksp) pcbddc->temp_solution_used = PETSC_FALSE;
154727b6a85dSStefano Zampini   }
154827b6a85dSStefano Zampini 
1549266e20e9SStefano Zampini   /* restore rhs to its original state (not needed for FETI-DP) */
15508d00608fSStefano Zampini   if (rhs && pcbddc->rhs_change) {
155127b6a85dSStefano Zampini     ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
15528d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_FALSE;
1553af140850Sstefano_zampini   }
15548efcfb23SStefano Zampini   /* restore ksp guess state */
15558efcfb23SStefano Zampini   if (ksp) {
15568efcfb23SStefano Zampini     ierr = KSPSetInitialGuessNonzero(ksp,pcbddc->ksp_guess_nonzero);CHKERRQ(ierr);
15578ae0ca82SStefano Zampini     /* reset flag for exact dirichlet trick */
15588ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
1559af140850Sstefano_zampini   }
1560534831adSStefano Zampini   PetscFunctionReturn(0);
1561534831adSStefano Zampini }
1562af140850Sstefano_zampini 
15630c7d97c5SJed Brown /*
15640c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
15650c7d97c5SJed Brown                   by setting data structures and options.
15660c7d97c5SJed Brown 
15670c7d97c5SJed Brown    Input Parameter:
156853cdbc3dSStefano Zampini +  pc - the preconditioner context
15690c7d97c5SJed Brown 
15700c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
15710c7d97c5SJed Brown 
15720c7d97c5SJed Brown    Notes:
15730c7d97c5SJed Brown      The interface routine PCSetUp() is not usually called directly by
15740c7d97c5SJed Brown      the user, but instead is called by PCApply() if necessary.
15750c7d97c5SJed Brown */
157653cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
15770c7d97c5SJed Brown {
15780c7d97c5SJed Brown   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1579c703fcc7SStefano Zampini   PCBDDCSubSchurs sub_schurs;
15805e8657edSStefano Zampini   Mat_IS*         matis;
158108122e43SStefano Zampini   MatNullSpace    nearnullspace;
158235509ce9Sstefano_zampini   Mat             lA;
158335509ce9Sstefano_zampini   IS              lP,zerodiag = NULL;
158491e8d312SStefano Zampini   PetscInt        nrows,ncols;
158586bfa4cfSStefano Zampini   PetscMPIInt     size;
1586c703fcc7SStefano Zampini   PetscBool       computesubschurs;
15878de1fae6SStefano Zampini   PetscBool       computeconstraintsmatrix;
15883b03f7bbSStefano Zampini   PetscBool       new_nearnullspace_provided,ismatis,rl;
1589c703fcc7SStefano Zampini   PetscErrorCode  ierr;
15900c7d97c5SJed Brown 
15910c7d97c5SJed Brown   PetscFunctionBegin;
15925e8657edSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATIS,&ismatis);CHKERRQ(ierr);
15936c4ed002SBarry Smith   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner requires matrix of type MATIS");
159491e8d312SStefano Zampini   ierr = MatGetSize(pc->pmat,&nrows,&ncols);CHKERRQ(ierr);
15956c4ed002SBarry Smith   if (nrows != ncols) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCBDDC preconditioner requires a square preconditioning matrix");
159686bfa4cfSStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
159786bfa4cfSStefano Zampini 
15985e8657edSStefano Zampini   matis = (Mat_IS*)pc->pmat->data;
1599f4ddd8eeSStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */
16003b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
160171582508SStefano Zampini      Also, BDDC builds its own KSP for the Dirichlet problem */
16023b03f7bbSStefano Zampini   rl = pcbddc->recompute_topography;
16033b03f7bbSStefano Zampini   if (!pc->setupcalled || pc->flag == DIFFERENT_NONZERO_PATTERN) rl = PETSC_TRUE;
16043b03f7bbSStefano Zampini   ierr = MPIU_Allreduce(&rl,&pcbddc->recompute_topography,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1605c83e1ba7SStefano Zampini   if (pcbddc->recompute_topography) {
1606c83e1ba7SStefano Zampini     pcbddc->graphanalyzed    = PETSC_FALSE;
1607c83e1ba7SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1608c83e1ba7SStefano Zampini   } else {
16098de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_FALSE;
1610c83e1ba7SStefano Zampini   }
1611b087196eSStefano Zampini 
1612b087196eSStefano Zampini   /* check parameters' compatibility */
1613b7ab4a40SStefano Zampini   if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE;
1614bd2a564bSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_threshold[0] != 0.0 || pcbddc->adaptive_threshold[1] != 0.0);
161586bfa4cfSStefano Zampini   pcbddc->use_deluxe_scaling   = (PetscBool)(pcbddc->use_deluxe_scaling && size > 1);
161686bfa4cfSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_selection && size > 1);
1617bf3a8328SStefano Zampini   pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined);
1618862806e4SStefano Zampini   if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE;
1619862806e4SStefano Zampini 
16205a95e1ceSStefano Zampini   computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling);
162116909a7fSStefano Zampini 
162271582508SStefano Zampini   /* activate all connected components if the netflux has been requested */
1623bb05f991SStefano Zampini   if (pcbddc->compute_nonetflux) {
1624bb05f991SStefano Zampini     pcbddc->use_vertices = PETSC_TRUE;
1625bb05f991SStefano Zampini     pcbddc->use_edges    = PETSC_TRUE;
1626bb05f991SStefano Zampini     pcbddc->use_faces    = PETSC_TRUE;
1627bb05f991SStefano Zampini   }
1628bb05f991SStefano Zampini 
1629f4ddd8eeSStefano Zampini   /* Get stdout for dbg */
163070cf5478SStefano Zampini   if (pcbddc->dbg_flag) {
163170cf5478SStefano Zampini     if (!pcbddc->dbg_viewer) {
163258a03d70SStefano Zampini       pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc));
1633f4ddd8eeSStefano Zampini     }
1634d9869140SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
163558a03d70SStefano Zampini     ierr = PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
1636f4ddd8eeSStefano Zampini   }
1637f4ddd8eeSStefano Zampini 
1638c703fcc7SStefano Zampini   /* process topology information */
163943371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_Topology[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
164071582508SStefano Zampini   if (pcbddc->recompute_topography) {
164171582508SStefano Zampini     ierr = PCBDDCComputeLocalTopologyInfo(pc);CHKERRQ(ierr);
1642c703fcc7SStefano Zampini     if (pcbddc->discretegradient) {
1643a13144ffSStefano Zampini       ierr = PCBDDCNedelecSupport(pc);CHKERRQ(ierr);
1644a13144ffSStefano Zampini     }
1645c703fcc7SStefano Zampini   }
16464f819b78SStefano Zampini   if (pcbddc->corner_selected) pcbddc->use_vertices = PETSC_TRUE;
1647a13144ffSStefano Zampini 
1648c703fcc7SStefano Zampini   /* change basis if requested by the user */
16495e8657edSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) {
16505e8657edSStefano Zampini     /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */
16515e8657edSStefano Zampini     pcbddc->use_change_of_basis = PETSC_FALSE;
16525e8657edSStefano Zampini     ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
16535e8657edSStefano Zampini   } else {
1654b96c3477SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
16555e8657edSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
16565e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
1657d16cbb6bSStefano Zampini   }
1658d16cbb6bSStefano Zampini 
16594f1b2e48SStefano Zampini   /*
1660c703fcc7SStefano Zampini      Compute change of basis on local pressures (aka zerodiag dofs) with the benign trick
16614f1b2e48SStefano Zampini      This should come earlier then PCISSetUp for extracting the correct subdomain matrices
16624f1b2e48SStefano Zampini   */
16631dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
1664d16cbb6bSStefano Zampini   if (pcbddc->benign_saddle_point) {
16659f47a83aSStefano Zampini     PC_IS* pcis = (PC_IS*)pc->data;
16669f47a83aSStefano Zampini 
166705b28244SStefano Zampini     if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE;
16683b03f7bbSStefano Zampini     /* detect local saddle point and change the basis in pcbddc->local_mat */
16693b03f7bbSStefano Zampini     ierr = PCBDDCBenignDetectSaddlePoint(pc,(PetscBool)(!pcbddc->recompute_topography),&zerodiag);CHKERRQ(ierr);
1670a3df083aSStefano Zampini     /* pop B0 mat from local mat */
1671c263805aSStefano Zampini     ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
16721dd7afcfSStefano Zampini     /* give pcis a hint to not reuse submatrices during PCISCreate */
16731dd7afcfSStefano Zampini     if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) {
16741dd7afcfSStefano Zampini       if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) {
16751dd7afcfSStefano Zampini         pcis->reusesubmatrices = PETSC_FALSE;
16761dd7afcfSStefano Zampini       } else {
1677a3df083aSStefano Zampini         pcis->reusesubmatrices = PETSC_TRUE;
16781dd7afcfSStefano Zampini       }
1679a3df083aSStefano Zampini     } else {
16809f47a83aSStefano Zampini       pcis->reusesubmatrices = PETSC_FALSE;
1681674ae819SStefano Zampini     }
1682a3df083aSStefano Zampini   }
168327b6a85dSStefano Zampini 
16848037d520SStefano Zampini   /* propagate relevant information */
168506a4e24aSStefano Zampini   if (matis->A->symmetric_set) {
168606a4e24aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
168706a4e24aSStefano Zampini   }
168806a4e24aSStefano Zampini   if (matis->A->spd_set) {
168906a4e24aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SPD,matis->A->spd);CHKERRQ(ierr);
169006a4e24aSStefano Zampini   }
1691e496cd5dSStefano Zampini 
16925e8657edSStefano Zampini   /* Set up all the "iterative substructuring" common block without computing solvers */
16935e8657edSStefano Zampini   {
16945e8657edSStefano Zampini     Mat temp_mat;
16955e8657edSStefano Zampini 
16965e8657edSStefano Zampini     temp_mat = matis->A;
16975e8657edSStefano Zampini     matis->A = pcbddc->local_mat;
1698d9869140SStefano Zampini     ierr = PCISSetUp(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
16995e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
17005e8657edSStefano Zampini     matis->A = temp_mat;
17015e8657edSStefano Zampini   }
1702684f6988SStefano Zampini 
170381d14e9dSStefano Zampini   /* Analyze interface */
170464ac59b8SStefano Zampini   if (!pcbddc->graphanalyzed) {
1705674ae819SStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
17068de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1707345ecf6cSStefano Zampini     if (pcbddc->adaptive_selection && !pcbddc->use_deluxe_scaling && !pcbddc->mat_graph->twodim) {
17084247aa23Sstefano_zampini       SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot compute the adaptive primal space for a problem with 3D edges without deluxe scaling");
1709345ecf6cSStefano Zampini     }
1710a198735bSStefano Zampini     if (pcbddc->compute_nonetflux) {
1711669cc0f4SStefano Zampini       MatNullSpace nnfnnsp;
1712669cc0f4SStefano Zampini 
171321ef3d20SStefano Zampini       if (!pcbddc->divudotp) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Missing divudotp operator");
17148ae0ca82SStefano Zampini       ierr = PCBDDCComputeNoNetFlux(pc->pmat,pcbddc->divudotp,pcbddc->divudotp_trans,pcbddc->divudotp_vl2l,pcbddc->mat_graph,&nnfnnsp);CHKERRQ(ierr);
171571582508SStefano Zampini       /* TODO what if a nearnullspace is already attached? */
17168037d520SStefano Zampini       if (nnfnnsp) {
1717669cc0f4SStefano Zampini         ierr = MatSetNearNullSpace(pc->pmat,nnfnnsp);CHKERRQ(ierr);
1718669cc0f4SStefano Zampini         ierr = MatNullSpaceDestroy(&nnfnnsp);CHKERRQ(ierr);
1719669cc0f4SStefano Zampini       }
1720674ae819SStefano Zampini     }
17218037d520SStefano Zampini   }
172243371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_Topology[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
1723fb8d54d4SStefano Zampini 
17245408967cSStefano Zampini   /* check existence of a divergence free extension, i.e.
17255408967cSStefano Zampini      b(v_I,p_0) = 0 for all v_I (raise error if not).
17265408967cSStefano Zampini      Also, check that PCBDDCBenignGetOrSetP0 works */
1727ff1f7e73Sstefano_zampini   if (pcbddc->benign_saddle_point && pcbddc->dbg_flag > 1) {
17285408967cSStefano Zampini     ierr = PCBDDCBenignCheck(pc,zerodiag);CHKERRQ(ierr);
172909f581a4SStefano Zampini   }
17304f1b2e48SStefano Zampini   ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
173106f24817SStefano Zampini 
1732b96c3477SStefano Zampini   /* Setup local dirichlet solver ksp_D and sub_schurs solvers */
1733c703fcc7SStefano Zampini   if (computesubschurs && pcbddc->recompute_topography) {
173408122e43SStefano Zampini     ierr = PCBDDCInitSubSchurs(pc);CHKERRQ(ierr);
1735b1b3d7a2SStefano Zampini   }
17369d54b7f4SStefano Zampini   /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/
17379d54b7f4SStefano Zampini   if (!pcbddc->use_deluxe_scaling) {
17389d54b7f4SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
17399d54b7f4SStefano Zampini   }
1740c703fcc7SStefano Zampini 
1741c703fcc7SStefano Zampini   /* finish setup solvers and do adaptive selection of constraints */
1742b334f244SStefano Zampini   sub_schurs = pcbddc->sub_schurs;
1743b334f244SStefano Zampini   if (sub_schurs && sub_schurs->schur_explicit) {
17442070dbb6SStefano Zampini     if (computesubschurs) {
174508122e43SStefano Zampini       ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
17462070dbb6SStefano Zampini     }
1747d5574798SStefano Zampini     ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
1748d5574798SStefano Zampini   } else {
1749d5574798SStefano Zampini     ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
17502070dbb6SStefano Zampini     if (computesubschurs) {
1751d5574798SStefano Zampini       ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
1752d5574798SStefano Zampini     }
17532070dbb6SStefano Zampini   }
175408122e43SStefano Zampini   if (pcbddc->adaptive_selection) {
175508122e43SStefano Zampini     ierr = PCBDDCAdaptiveSelection(pc);CHKERRQ(ierr);
17568de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1757b7eb3628SStefano Zampini   }
1758684f6988SStefano Zampini 
1759f4ddd8eeSStefano Zampini   /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */
1760fb8d54d4SStefano Zampini   new_nearnullspace_provided = PETSC_FALSE;
1761f4ddd8eeSStefano Zampini   ierr = MatGetNearNullSpace(pc->pmat,&nearnullspace);CHKERRQ(ierr);
1762f4ddd8eeSStefano Zampini   if (pcbddc->onearnullspace) { /* already used nearnullspace */
1763f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* near null space attached to mat has been destroyed */
1764f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1765f4ddd8eeSStefano Zampini     } else {
1766f4ddd8eeSStefano Zampini       /* determine if the two nullspaces are different (should be lightweight) */
1767f4ddd8eeSStefano Zampini       if (nearnullspace != pcbddc->onearnullspace) {
1768f4ddd8eeSStefano Zampini         new_nearnullspace_provided = PETSC_TRUE;
1769165b64e2SStefano Zampini       } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */
1770f4ddd8eeSStefano Zampini         PetscInt         i;
1771165b64e2SStefano Zampini         const Vec        *nearnullvecs;
1772165b64e2SStefano Zampini         PetscObjectState state;
1773165b64e2SStefano Zampini         PetscInt         nnsp_size;
1774165b64e2SStefano Zampini         ierr = MatNullSpaceGetVecs(nearnullspace,NULL,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
1775f4ddd8eeSStefano Zampini         for (i=0;i<nnsp_size;i++) {
1776f4ddd8eeSStefano Zampini           ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&state);CHKERRQ(ierr);
1777165b64e2SStefano Zampini           if (pcbddc->onearnullvecs_state[i] != state) {
1778f4ddd8eeSStefano Zampini             new_nearnullspace_provided = PETSC_TRUE;
1779f4ddd8eeSStefano Zampini             break;
1780f4ddd8eeSStefano Zampini           }
1781f4ddd8eeSStefano Zampini         }
1782f4ddd8eeSStefano Zampini       }
1783f4ddd8eeSStefano Zampini     }
1784f4ddd8eeSStefano Zampini   } else {
1785f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* both nearnullspaces are null */
1786f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_FALSE;
1787f4ddd8eeSStefano Zampini     } else { /* nearnullspace attached later */
1788f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1789f4ddd8eeSStefano Zampini     }
1790f4ddd8eeSStefano Zampini   }
1791f4ddd8eeSStefano Zampini 
1792f4ddd8eeSStefano Zampini   /* Setup constraints and related work vectors */
1793727cdba6SStefano Zampini   /* reset primal space flags */
179443371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_LocalWork[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
1795f4ddd8eeSStefano Zampini   pcbddc->new_primal_space = PETSC_FALSE;
1796727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_FALSE;
17978de1fae6SStefano Zampini   if (computeconstraintsmatrix || new_nearnullspace_provided) {
1798727cdba6SStefano Zampini     /* It also sets the primal space flags */
1799674ae819SStefano Zampini     ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr);
18009543d0ffSStefano Zampini   }
1801e7b262bdSStefano Zampini   /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */
1802f4ddd8eeSStefano Zampini   ierr = PCBDDCSetUpLocalWorkVectors(pc);CHKERRQ(ierr);
18035e8657edSStefano Zampini 
18045e8657edSStefano Zampini   if (pcbddc->use_change_of_basis) {
18055e8657edSStefano Zampini     PC_IS *pcis = (PC_IS*)(pc->data);
18065e8657edSStefano Zampini 
18075e8657edSStefano Zampini     ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
18084f1b2e48SStefano Zampini     if (pcbddc->benign_change) {
18091dd7afcfSStefano Zampini       ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
1810c263805aSStefano Zampini       /* pop B0 from pcbddc->local_mat */
1811c263805aSStefano Zampini       ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
1812c263805aSStefano Zampini     }
18135e8657edSStefano Zampini     /* get submatrices */
18145e8657edSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
18155e8657edSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
18165e8657edSStefano Zampini     ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);
18177dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB);CHKERRQ(ierr);
18187dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr);
18197dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr);
18203975b054SStefano Zampini     /* set flag in pcis to not reuse submatrices during PCISCreate */
18213975b054SStefano Zampini     pcis->reusesubmatrices = PETSC_FALSE;
18229c6a02ceSStefano Zampini   } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) {
1823b96c3477SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
18245e8657edSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
18255e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
18265e8657edSStefano Zampini   }
182735509ce9Sstefano_zampini 
182835509ce9Sstefano_zampini   /* interface pressure block row for B_C */
182935509ce9Sstefano_zampini   ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP" ,(PetscObject*)&lP);CHKERRQ(ierr);
183035509ce9Sstefano_zampini   ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA);CHKERRQ(ierr);
183135509ce9Sstefano_zampini   if (lA && lP) {
183235509ce9Sstefano_zampini     PC_IS*    pcis = (PC_IS*)pc->data;
183335509ce9Sstefano_zampini     Mat       B_BI,B_BB,Bt_BI,Bt_BB;
183435509ce9Sstefano_zampini     PetscBool issym;
183535509ce9Sstefano_zampini     ierr = MatIsSymmetric(lA,PETSC_SMALL,&issym);CHKERRQ(ierr);
18366cc1294bSstefano_zampini     if (issym) {
18377dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI);CHKERRQ(ierr);
18387dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB);CHKERRQ(ierr);
183935509ce9Sstefano_zampini       ierr = MatCreateTranspose(B_BI,&Bt_BI);CHKERRQ(ierr);
184035509ce9Sstefano_zampini       ierr = MatCreateTranspose(B_BB,&Bt_BB);CHKERRQ(ierr);
184135509ce9Sstefano_zampini     } else {
18427dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI);CHKERRQ(ierr);
18437dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB);CHKERRQ(ierr);
18447dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,pcis->is_I_local,lP,MAT_INITIAL_MATRIX,&Bt_BI);CHKERRQ(ierr);
18457dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,pcis->is_B_local,lP,MAT_INITIAL_MATRIX,&Bt_BB);CHKERRQ(ierr);
184635509ce9Sstefano_zampini     }
184735509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BI",(PetscObject)B_BI);CHKERRQ(ierr);
184835509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BB",(PetscObject)B_BB);CHKERRQ(ierr);
184935509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BI",(PetscObject)Bt_BI);CHKERRQ(ierr);
185035509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BB",(PetscObject)Bt_BB);CHKERRQ(ierr);
185135509ce9Sstefano_zampini     ierr = MatDestroy(&B_BI);CHKERRQ(ierr);
185235509ce9Sstefano_zampini     ierr = MatDestroy(&B_BB);CHKERRQ(ierr);
185335509ce9Sstefano_zampini     ierr = MatDestroy(&Bt_BI);CHKERRQ(ierr);
185435509ce9Sstefano_zampini     ierr = MatDestroy(&Bt_BB);CHKERRQ(ierr);
185535509ce9Sstefano_zampini   }
185643371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_LocalWork[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
185735509ce9Sstefano_zampini 
1858b96c3477SStefano Zampini   /* SetUp coarse and local Neumann solvers */
185999cc7994SStefano Zampini   ierr = PCBDDCSetUpSolvers(pc);CHKERRQ(ierr);
1860b96c3477SStefano Zampini   /* SetUp Scaling operator */
18619d54b7f4SStefano Zampini   if (pcbddc->use_deluxe_scaling) {
1862674ae819SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
18630c7d97c5SJed Brown   }
1864c703fcc7SStefano Zampini 
18651dd7afcfSStefano Zampini   /* mark topography as done */
186656282151SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
18670369aaf7SStefano Zampini 
18681dd7afcfSStefano Zampini   /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */
18691dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_FALSE);CHKERRQ(ierr);
18701dd7afcfSStefano Zampini 
187158a03d70SStefano Zampini   if (pcbddc->dbg_flag) {
187258a03d70SStefano Zampini     ierr = PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
1873d9869140SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
18742b510759SStefano Zampini   }
18750c7d97c5SJed Brown   PetscFunctionReturn(0);
18760c7d97c5SJed Brown }
18770c7d97c5SJed Brown 
18780c7d97c5SJed Brown /*
187950efa1b5SStefano Zampini    PCApply_BDDC - Applies the BDDC operator to a vector.
18800c7d97c5SJed Brown 
18810c7d97c5SJed Brown    Input Parameters:
18820f202f7eSStefano Zampini +  pc - the preconditioner context
18830f202f7eSStefano Zampini -  r - input vector (global)
18840c7d97c5SJed Brown 
18850c7d97c5SJed Brown    Output Parameter:
18860c7d97c5SJed Brown .  z - output vector (global)
18870c7d97c5SJed Brown 
18880c7d97c5SJed Brown    Application Interface Routine: PCApply()
18890c7d97c5SJed Brown  */
189053cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
18910c7d97c5SJed Brown {
18920c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
18930c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1894b3338236SStefano Zampini   Mat               lA = NULL;
1895b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
18960c7d97c5SJed Brown   PetscErrorCode    ierr;
18973b03a366Sstefano_zampini   const PetscScalar one = 1.0;
18983b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
18992617d88aSStefano Zampini   const PetscScalar zero = 0.0;
19000c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
19010c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
1902b097fa66SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */
19030c7d97c5SJed Brown 
19040c7d97c5SJed Brown   PetscFunctionBegin;
1905f3d41395Sstefano_zampini   ierr = PetscCitationsRegister(citation,&cited);CHKERRQ(ierr);
1906b3338236SStefano Zampini   if (pcbddc->switch_static) {
1907b3338236SStefano Zampini     ierr = MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat,&lA);CHKERRQ(ierr);
1908b3338236SStefano Zampini   }
1909b3338236SStefano Zampini 
19101dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
19111dd7afcfSStefano Zampini     Vec swap;
191227b6a85dSStefano Zampini 
191327b6a85dSStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
19141dd7afcfSStefano Zampini     swap = pcbddc->work_change;
19151dd7afcfSStefano Zampini     pcbddc->work_change = r;
19161dd7afcfSStefano Zampini     r = swap;
19171dd7afcfSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
19189cc2a9b1Sstefano_zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) {
19191dd7afcfSStefano Zampini       ierr = VecCopy(r,pcis->vec1_global);CHKERRQ(ierr);
19208860a134SJunchao Zhang       ierr = VecLockReadPush(pcis->vec1_global);CHKERRQ(ierr);
19211dd7afcfSStefano Zampini     }
19221dd7afcfSStefano Zampini   }
192327b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
1924015636ebSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
1925efc2fbd9SStefano Zampini   }
19268ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1927b097fa66SStefano Zampini     ierr = VecCopy(r,z);CHKERRQ(ierr);
19280c7d97c5SJed Brown     /* First Dirichlet solve */
19290c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19300c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19310c7d97c5SJed Brown     /*
19320c7d97c5SJed Brown       Assembling right hand side for BDDC operator
1933b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
1934674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
19350c7d97c5SJed Brown     */
1936b097fa66SStefano Zampini     if (n_D) {
1937b097fa66SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1938c0decd05SBarry Smith       ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D);CHKERRQ(ierr);
19390c7d97c5SJed Brown       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
194016909a7fSStefano Zampini       if (pcbddc->switch_static) {
194116909a7fSStefano Zampini         ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
194216909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
194316909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
194416909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
1945b3338236SStefano Zampini           ierr = MatMult(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
194616909a7fSStefano Zampini         } else {
194716909a7fSStefano Zampini           ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1948b3338236SStefano Zampini           ierr = MatMult(lA,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
194916909a7fSStefano Zampini           ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
195016909a7fSStefano Zampini         }
195116909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
195216909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
195316909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
195416909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
195516909a7fSStefano Zampini       } else {
1956b097fa66SStefano Zampini         ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
195716909a7fSStefano Zampini       }
1958b097fa66SStefano Zampini     } else {
1959b097fa66SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1960b097fa66SStefano Zampini     }
19610c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
19620c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1963674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
1964b76ba322SStefano Zampini   } else {
19654fee134fSStefano Zampini     if (!pcbddc->benign_apply_coarse_only) {
1966674ae819SStefano Zampini       ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
1967b76ba322SStefano Zampini     }
19684fee134fSStefano Zampini   }
1969b76ba322SStefano Zampini 
19702617d88aSStefano Zampini   /* Apply interface preconditioner
19712617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
1972dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
19732617d88aSStefano Zampini 
1974674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
1975674ae819SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
19760c7d97c5SJed Brown 
19773b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
19780c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19790c7d97c5SJed Brown   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1980b097fa66SStefano Zampini   if (n_B) {
198116909a7fSStefano Zampini     if (pcbddc->switch_static) {
198216909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
198316909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
198416909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
198516909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
198616909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
1987b3338236SStefano Zampini         ierr = MatMult(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
198816909a7fSStefano Zampini       } else {
198916909a7fSStefano Zampini         ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1990b3338236SStefano Zampini         ierr = MatMult(lA,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
199116909a7fSStefano Zampini         ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
199216909a7fSStefano Zampini       }
199316909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
199416909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
199516909a7fSStefano Zampini     } else {
19960c7d97c5SJed Brown       ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
199716909a7fSStefano Zampini     }
199816909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
199916909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
2000b3338236SStefano Zampini       ierr = MatMult(lA,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
200116909a7fSStefano Zampini     } else {
200216909a7fSStefano Zampini       ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N);CHKERRQ(ierr);
2003b3338236SStefano Zampini       ierr = MatMult(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
200416909a7fSStefano Zampini       ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D);CHKERRQ(ierr);
200516909a7fSStefano Zampini     }
2006b097fa66SStefano Zampini   }
2007df187020SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
2008c0decd05SBarry Smith   ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec4_D);CHKERRQ(ierr);
2009efc2fbd9SStefano Zampini 
20108ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
2011b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2012b097fa66SStefano Zampini       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
2013b097fa66SStefano Zampini     } else {
2014b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
2015b097fa66SStefano Zampini     }
20160c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20170c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2018b097fa66SStefano Zampini   } else {
2019b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2020b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
2021b097fa66SStefano Zampini     } else {
2022b097fa66SStefano Zampini       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
2023b097fa66SStefano Zampini     }
2024b097fa66SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2025b097fa66SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2026b097fa66SStefano Zampini   }
202727b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
20281dd7afcfSStefano Zampini     if (pcbddc->benign_apply_coarse_only) {
2029580bdb30SBarry Smith       ierr = PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n);CHKERRQ(ierr);
20301dd7afcfSStefano Zampini     }
2031015636ebSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
2032efc2fbd9SStefano Zampini   }
20331f4df5f7SStefano Zampini 
20341dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2035f913dca9SStefano Zampini     pcbddc->work_change = r;
20361dd7afcfSStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
20371dd7afcfSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
20381dd7afcfSStefano Zampini   }
20390c7d97c5SJed Brown   PetscFunctionReturn(0);
20400c7d97c5SJed Brown }
204150efa1b5SStefano Zampini 
204250efa1b5SStefano Zampini /*
204350efa1b5SStefano Zampini    PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector.
204450efa1b5SStefano Zampini 
204550efa1b5SStefano Zampini    Input Parameters:
20460f202f7eSStefano Zampini +  pc - the preconditioner context
20470f202f7eSStefano Zampini -  r - input vector (global)
204850efa1b5SStefano Zampini 
204950efa1b5SStefano Zampini    Output Parameter:
205050efa1b5SStefano Zampini .  z - output vector (global)
205150efa1b5SStefano Zampini 
205250efa1b5SStefano Zampini    Application Interface Routine: PCApplyTranspose()
205350efa1b5SStefano Zampini  */
205450efa1b5SStefano Zampini PetscErrorCode PCApplyTranspose_BDDC(PC pc,Vec r,Vec z)
205550efa1b5SStefano Zampini {
205650efa1b5SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
205750efa1b5SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
2058b3338236SStefano Zampini   Mat               lA = NULL;
2059b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
206050efa1b5SStefano Zampini   PetscErrorCode    ierr;
206150efa1b5SStefano Zampini   const PetscScalar one = 1.0;
206250efa1b5SStefano Zampini   const PetscScalar m_one = -1.0;
206350efa1b5SStefano Zampini   const PetscScalar zero = 0.0;
206450efa1b5SStefano Zampini 
206550efa1b5SStefano Zampini   PetscFunctionBegin;
2066f3d41395Sstefano_zampini   ierr = PetscCitationsRegister(citation,&cited);CHKERRQ(ierr);
2067b3338236SStefano Zampini   if (pcbddc->switch_static) {
2068b3338236SStefano Zampini     ierr = MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat,&lA);CHKERRQ(ierr);
2069b3338236SStefano Zampini   }
20701dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
20711dd7afcfSStefano Zampini     Vec swap;
207227b6a85dSStefano Zampini 
207327b6a85dSStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
20741dd7afcfSStefano Zampini     swap = pcbddc->work_change;
20751dd7afcfSStefano Zampini     pcbddc->work_change = r;
20761dd7afcfSStefano Zampini     r = swap;
207727b6a85dSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
20788ae0ca82SStefano Zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->exact_dirichlet_trick_app && pcbddc->change_interior) {
207927b6a85dSStefano Zampini       ierr = VecCopy(r,pcis->vec1_global);CHKERRQ(ierr);
20808860a134SJunchao Zhang       ierr = VecLockReadPush(pcis->vec1_global);CHKERRQ(ierr);
20811dd7afcfSStefano Zampini     }
208227b6a85dSStefano Zampini   }
208327b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
2084537c1cdfSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
2085537c1cdfSStefano Zampini   }
20868ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
2087b097fa66SStefano Zampini     ierr = VecCopy(r,z);CHKERRQ(ierr);
208850efa1b5SStefano Zampini     /* First Dirichlet solve */
208950efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
209050efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
209150efa1b5SStefano Zampini     /*
209250efa1b5SStefano Zampini       Assembling right hand side for BDDC operator
2093b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
209450efa1b5SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
209550efa1b5SStefano Zampini     */
2096b097fa66SStefano Zampini     if (n_D) {
2097b097fa66SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
2098c0decd05SBarry Smith       ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D);CHKERRQ(ierr);
209950efa1b5SStefano Zampini       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
210016909a7fSStefano Zampini       if (pcbddc->switch_static) {
210116909a7fSStefano Zampini         ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
210216909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
210316909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
210416909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
2105b3338236SStefano Zampini           ierr = MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
210616909a7fSStefano Zampini         } else {
210716909a7fSStefano Zampini           ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
2108b3338236SStefano Zampini           ierr = MatMultTranspose(lA,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
210916909a7fSStefano Zampini           ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
211016909a7fSStefano Zampini         }
211116909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
211216909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
211316909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
211416909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
211516909a7fSStefano Zampini       } else {
2116b097fa66SStefano Zampini         ierr = MatMultTranspose(pcis->A_IB,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
211716909a7fSStefano Zampini       }
2118b097fa66SStefano Zampini     } else {
2119b097fa66SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
2120b097fa66SStefano Zampini     }
212150efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
212250efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
212350efa1b5SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
212450efa1b5SStefano Zampini   } else {
212550efa1b5SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
212650efa1b5SStefano Zampini   }
212750efa1b5SStefano Zampini 
212850efa1b5SStefano Zampini   /* Apply interface preconditioner
212950efa1b5SStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
2130dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_TRUE);CHKERRQ(ierr);
213150efa1b5SStefano Zampini 
213250efa1b5SStefano Zampini   /* Apply transpose of partition of unity operator */
213350efa1b5SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
213450efa1b5SStefano Zampini 
213550efa1b5SStefano Zampini   /* Second Dirichlet solve and assembling of output */
213650efa1b5SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
213750efa1b5SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2138b097fa66SStefano Zampini   if (n_B) {
213916909a7fSStefano Zampini     if (pcbddc->switch_static) {
214016909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
214116909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
214216909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
214316909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
214416909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
2145b3338236SStefano Zampini         ierr = MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
214616909a7fSStefano Zampini       } else {
214716909a7fSStefano Zampini         ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
2148b3338236SStefano Zampini         ierr = MatMultTranspose(lA,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
214916909a7fSStefano Zampini         ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
215016909a7fSStefano Zampini       }
215116909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
215216909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
215316909a7fSStefano Zampini     } else {
215450efa1b5SStefano Zampini       ierr = MatMultTranspose(pcis->A_BI,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
215516909a7fSStefano Zampini     }
215616909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
215716909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
2158b3338236SStefano Zampini       ierr = MatMultTranspose(lA,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
215916909a7fSStefano Zampini     } else {
216016909a7fSStefano Zampini       ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N);CHKERRQ(ierr);
2161b3338236SStefano Zampini       ierr = MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
216216909a7fSStefano Zampini       ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D);CHKERRQ(ierr);
216316909a7fSStefano Zampini     }
2164b097fa66SStefano Zampini   }
2165b0147a47SStefano Zampini   ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
2166c0decd05SBarry Smith   ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec4_D);CHKERRQ(ierr);
21678ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
2168b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2169b097fa66SStefano Zampini       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
2170b097fa66SStefano Zampini     } else {
2171b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
2172b097fa66SStefano Zampini     }
217350efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
217450efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2175b097fa66SStefano Zampini   } else {
2176b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2177b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
2178b097fa66SStefano Zampini     } else {
2179b097fa66SStefano Zampini       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
2180b097fa66SStefano Zampini     }
2181b097fa66SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2182b097fa66SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2183b097fa66SStefano Zampini   }
218427b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
2185537c1cdfSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
2186537c1cdfSStefano Zampini   }
21871dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2188f913dca9SStefano Zampini     pcbddc->work_change = r;
21891dd7afcfSStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
21901dd7afcfSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
21911dd7afcfSStefano Zampini   }
219250efa1b5SStefano Zampini   PetscFunctionReturn(0);
219350efa1b5SStefano Zampini }
2194674ae819SStefano Zampini 
21959326c5c6Sstefano_zampini PetscErrorCode PCReset_BDDC(PC pc)
2196da1bb401SStefano Zampini {
2197da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
21989326c5c6Sstefano_zampini   PC_IS          *pcis = (PC_IS*)pc->data;
21999326c5c6Sstefano_zampini   KSP            kspD,kspR,kspC;
2200da1bb401SStefano Zampini   PetscErrorCode ierr;
2201da1bb401SStefano Zampini 
2202da1bb401SStefano Zampini   PetscFunctionBegin;
2203674ae819SStefano Zampini   /* free BDDC custom data  */
2204674ae819SStefano Zampini   ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr);
2205674ae819SStefano Zampini   /* destroy objects related to topography */
2206674ae819SStefano Zampini   ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
220734a97f8cSStefano Zampini   /* destroy objects for scaling operator */
2208674ae819SStefano Zampini   ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
2209674ae819SStefano Zampini   /* free solvers stuff */
2210674ae819SStefano Zampini   ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
221162a6ff1dSStefano Zampini   /* free global vectors needed in presolve */
221262a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr);
221362a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr);
22141dd7afcfSStefano Zampini   /* free data created by PCIS */
22151dd7afcfSStefano Zampini   ierr = PCISDestroy(pc);CHKERRQ(ierr);
22169326c5c6Sstefano_zampini 
22179326c5c6Sstefano_zampini   /* restore defaults */
22189326c5c6Sstefano_zampini   kspD = pcbddc->ksp_D;
22199326c5c6Sstefano_zampini   kspR = pcbddc->ksp_R;
22209326c5c6Sstefano_zampini   kspC = pcbddc->coarse_ksp;
22219326c5c6Sstefano_zampini   ierr = PetscMemzero(pc->data,sizeof(*pcbddc));CHKERRQ(ierr);
22229326c5c6Sstefano_zampini   pcis->n_neigh                     = -1;
22239326c5c6Sstefano_zampini   pcis->scaling_factor              = 1.0;
22249326c5c6Sstefano_zampini   pcis->reusesubmatrices            = PETSC_TRUE;
22259326c5c6Sstefano_zampini   pcbddc->use_local_adj             = PETSC_TRUE;
22269326c5c6Sstefano_zampini   pcbddc->use_vertices              = PETSC_TRUE;
22279326c5c6Sstefano_zampini   pcbddc->use_edges                 = PETSC_TRUE;
22289326c5c6Sstefano_zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
22299326c5c6Sstefano_zampini   pcbddc->vertex_size               = 1;
22309326c5c6Sstefano_zampini   pcbddc->recompute_topography      = PETSC_TRUE;
22319326c5c6Sstefano_zampini   pcbddc->coarse_size               = -1;
22329326c5c6Sstefano_zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
22339326c5c6Sstefano_zampini   pcbddc->coarsening_ratio          = 8;
22349326c5c6Sstefano_zampini   pcbddc->coarse_eqs_per_proc       = 1;
22359326c5c6Sstefano_zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
22369326c5c6Sstefano_zampini   pcbddc->nedfield                  = -1;
22379326c5c6Sstefano_zampini   pcbddc->nedglobal                 = PETSC_TRUE;
22389326c5c6Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
22399326c5c6Sstefano_zampini   pcbddc->sub_schurs_layers         = -1;
22409326c5c6Sstefano_zampini   pcbddc->ksp_D                     = kspD;
22419326c5c6Sstefano_zampini   pcbddc->ksp_R                     = kspR;
22429326c5c6Sstefano_zampini   pcbddc->coarse_ksp                = kspC;
22439326c5c6Sstefano_zampini   PetscFunctionReturn(0);
22449326c5c6Sstefano_zampini }
22459326c5c6Sstefano_zampini 
22469326c5c6Sstefano_zampini PetscErrorCode PCDestroy_BDDC(PC pc)
22479326c5c6Sstefano_zampini {
22489326c5c6Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
22499326c5c6Sstefano_zampini   PetscErrorCode ierr;
22509326c5c6Sstefano_zampini 
22519326c5c6Sstefano_zampini   PetscFunctionBegin;
22529326c5c6Sstefano_zampini   ierr = PCReset_BDDC(pc);CHKERRQ(ierr);
22539326c5c6Sstefano_zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
22549326c5c6Sstefano_zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
22559326c5c6Sstefano_zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
2256a13144ffSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",NULL);CHKERRQ(ierr);
2257a198735bSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",NULL);CHKERRQ(ierr);
2258906d46d4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",NULL);CHKERRQ(ierr);
2259674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr);
226030368db7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",NULL);CHKERRQ(ierr);
2261bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr);
22622b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL);CHKERRQ(ierr);
2263b8ffe317SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL);CHKERRQ(ierr);
22642b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL);CHKERRQ(ierr);
2265bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
226682ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
2267bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
226882ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
2269bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
227082ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
2271bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
2272785d1243SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
2273bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr);
227463602bcaSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",NULL);CHKERRQ(ierr);
2275bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr);
2276bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr);
2277bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr);
2278bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr);
2279a06fd7f2SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",NULL);CHKERRQ(ierr);
2280ab8c8b98SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",NULL);CHKERRQ(ierr);
2281674ae819SStefano Zampini   ierr = PetscFree(pc->data);CHKERRQ(ierr);
2282da1bb401SStefano Zampini   PetscFunctionReturn(0);
2283da1bb401SStefano Zampini }
22841e6b0712SBarry Smith 
2285ab8c8b98SStefano Zampini static PetscErrorCode PCSetCoordinates_BDDC(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
2286ab8c8b98SStefano Zampini {
2287ab8c8b98SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2288ab8c8b98SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
2289ab8c8b98SStefano Zampini   PetscErrorCode ierr;
2290ab8c8b98SStefano Zampini 
2291ab8c8b98SStefano Zampini   PetscFunctionBegin;
2292ab8c8b98SStefano Zampini   ierr = PetscFree(mat_graph->coords);CHKERRQ(ierr);
2293ab8c8b98SStefano Zampini   ierr = PetscMalloc1(nloc*dim,&mat_graph->coords);CHKERRQ(ierr);
2294580bdb30SBarry Smith   ierr = PetscArraycpy(mat_graph->coords,coords,nloc*dim);CHKERRQ(ierr);
2295ab8c8b98SStefano Zampini   mat_graph->cnloc = nloc;
2296ab8c8b98SStefano Zampini   mat_graph->cdim  = dim;
2297ab8c8b98SStefano Zampini   mat_graph->cloc  = PETSC_FALSE;
22984f819b78SStefano Zampini   /* flg setup */
22994f819b78SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
23004f819b78SStefano Zampini   pcbddc->corner_selected = PETSC_FALSE;
2301ab8c8b98SStefano Zampini   PetscFunctionReturn(0);
2302ab8c8b98SStefano Zampini }
2303ab8c8b98SStefano Zampini 
2304a06fd7f2SStefano Zampini static PetscErrorCode PCPreSolveChangeRHS_BDDC(PC pc, PetscBool* change)
2305a06fd7f2SStefano Zampini {
2306a06fd7f2SStefano Zampini   PetscFunctionBegin;
2307a06fd7f2SStefano Zampini   *change = PETSC_TRUE;
2308a06fd7f2SStefano Zampini   PetscFunctionReturn(0);
2309a06fd7f2SStefano Zampini }
2310a06fd7f2SStefano Zampini 
23113425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
23123425bc38SStefano Zampini {
2313674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
2314266e20e9SStefano Zampini   Vec            work;
23153425bc38SStefano Zampini   PC_IS*         pcis;
23163425bc38SStefano Zampini   PC_BDDC*       pcbddc;
23173425bc38SStefano Zampini   PetscErrorCode ierr;
23180c7d97c5SJed Brown 
23193425bc38SStefano Zampini   PetscFunctionBegin;
23203425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
23213425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
23223425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
23233425bc38SStefano Zampini 
2324229984c5Sstefano_zampini   ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr);
2325229984c5Sstefano_zampini   /* copy rhs since we may change it during PCPreSolve_BDDC */
2326229984c5Sstefano_zampini   if (!pcbddc->original_rhs) {
2327229984c5Sstefano_zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
2328229984c5Sstefano_zampini   }
23296cc1294bSstefano_zampini   if (mat_ctx->rhs_flip) {
23306cc1294bSstefano_zampini     ierr = VecPointwiseMult(pcbddc->original_rhs,standard_rhs,mat_ctx->rhs_flip);CHKERRQ(ierr);
23316cc1294bSstefano_zampini   } else {
2332229984c5Sstefano_zampini     ierr = VecCopy(standard_rhs,pcbddc->original_rhs);CHKERRQ(ierr);
23336cc1294bSstefano_zampini   }
2334af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
2335229984c5Sstefano_zampini     /* interface pressure rhs */
2336022d8d2bSstefano_zampini     ierr = VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2337022d8d2bSstefano_zampini     ierr = VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2338229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2339229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
23406cc1294bSstefano_zampini     if (!mat_ctx->rhs_flip) {
2341229984c5Sstefano_zampini       ierr = VecScale(fetidp_flux_rhs,-1.);CHKERRQ(ierr);
2342229984c5Sstefano_zampini     }
23436cc1294bSstefano_zampini   }
2344c08af4c6SStefano Zampini   /*
2345c08af4c6SStefano Zampini      change of basis for physical rhs if needed
2346c08af4c6SStefano Zampini      It also changes the rhs in case of dirichlet boundaries
2347c08af4c6SStefano Zampini   */
23483738a8e6SStefano Zampini   ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,pcbddc->original_rhs,NULL);CHKERRQ(ierr);
2349fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
23503738a8e6SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcbddc->original_rhs,pcbddc->work_change);CHKERRQ(ierr);
23513738a8e6SStefano Zampini     work = pcbddc->work_change;
2352fc17d649SStefano Zampini    } else {
23533738a8e6SStefano Zampini     work = pcbddc->original_rhs;
2354fc17d649SStefano Zampini   }
23553425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
2356266e20e9SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2357266e20e9SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2358fb223d50SStefano Zampini   /* scale rhs since it should be unassembled */
2359fb223d50SStefano Zampini   /* TODO use counter scaling? (also below) */
2360266e20e9SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2361266e20e9SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2362674ae819SStefano Zampini   /* Apply partition of unity */
23633425bc38SStefano Zampini   ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
2364266e20e9SStefano Zampini   /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
23658eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
23663425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
23673425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
2368c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
23693425bc38SStefano Zampini     ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr);
23703425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr);
2371266e20e9SStefano Zampini     ierr = VecSet(work,0.0);CHKERRQ(ierr);
2372266e20e9SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2373266e20e9SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2374266e20e9SStefano Zampini     /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
2375266e20e9SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2376266e20e9SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
23773425bc38SStefano Zampini     ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
23783425bc38SStefano Zampini   }
23793425bc38SStefano Zampini   /* BDDC rhs */
23803425bc38SStefano Zampini   ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr);
23818eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
23823425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
23833425bc38SStefano Zampini   }
23843425bc38SStefano Zampini   /* apply BDDC */
2385580bdb30SBarry Smith   ierr = PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n);CHKERRQ(ierr);
2386dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
2387580bdb30SBarry Smith   ierr = PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n);CHKERRQ(ierr);
2388229984c5Sstefano_zampini 
23893425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
23903425bc38SStefano Zampini   ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr);
23913425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
23923425bc38SStefano Zampini   ierr = VecScatterEnd(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2393229984c5Sstefano_zampini   /* Add contribution to interface pressures */
2394229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
2395229984c5Sstefano_zampini     ierr = MatMult(mat_ctx->B_BB,pcis->vec1_B,mat_ctx->vP);CHKERRQ(ierr);
2396229984c5Sstefano_zampini     if (pcbddc->switch_static) {
2397229984c5Sstefano_zampini       ierr = MatMultAdd(mat_ctx->B_BI,pcis->vec1_D,mat_ctx->vP,mat_ctx->vP);CHKERRQ(ierr);
2398229984c5Sstefano_zampini     }
2399229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2400229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2401229984c5Sstefano_zampini   }
24023425bc38SStefano Zampini   PetscFunctionReturn(0);
24033425bc38SStefano Zampini }
24041e6b0712SBarry Smith 
24053425bc38SStefano Zampini /*@
24060f202f7eSStefano Zampini  PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side
24073425bc38SStefano Zampini 
24083425bc38SStefano Zampini    Collective
24093425bc38SStefano Zampini 
24103425bc38SStefano Zampini    Input Parameters:
24110f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix object obtained by a call to PCBDDCCreateFETIDPOperators
24120f202f7eSStefano Zampini -  standard_rhs    - the right-hand side of the original linear system
24133425bc38SStefano Zampini 
24143425bc38SStefano Zampini    Output Parameters:
24150f202f7eSStefano Zampini .  fetidp_flux_rhs - the right-hand side for the FETI-DP linear system
24163425bc38SStefano Zampini 
24173425bc38SStefano Zampini    Level: developer
24183425bc38SStefano Zampini 
24193425bc38SStefano Zampini    Notes:
24203425bc38SStefano Zampini 
24210f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetSolution
24223425bc38SStefano Zampini @*/
24233425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
24243425bc38SStefano Zampini {
2425674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
24263425bc38SStefano Zampini   PetscErrorCode ierr;
24273425bc38SStefano Zampini 
24283425bc38SStefano Zampini   PetscFunctionBegin;
2429266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1);
2430266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_rhs,VEC_CLASSID,2);
2431266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_rhs,VEC_CLASSID,3);
24323425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
2433163d334eSBarry Smith   ierr = PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr);
24343425bc38SStefano Zampini   PetscFunctionReturn(0);
24353425bc38SStefano Zampini }
24361e6b0712SBarry Smith 
24373425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
24383425bc38SStefano Zampini {
2439674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
24403425bc38SStefano Zampini   PC_IS*         pcis;
24413425bc38SStefano Zampini   PC_BDDC*       pcbddc;
24423425bc38SStefano Zampini   PetscErrorCode ierr;
2443229984c5Sstefano_zampini   Vec            work;
24443425bc38SStefano Zampini 
24453425bc38SStefano Zampini   PetscFunctionBegin;
24463425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
24473425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
24483425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
24493425bc38SStefano Zampini 
24503425bc38SStefano Zampini   /* apply B_delta^T */
2451af140850Sstefano_zampini   ierr = VecSet(pcis->vec1_B,0.);CHKERRQ(ierr);
24523425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
24533425bc38SStefano Zampini   ierr = VecScatterEnd(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
24543425bc38SStefano Zampini   ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
2455229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
2456229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2457229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2458229984c5Sstefano_zampini     ierr = MatMultAdd(mat_ctx->Bt_BB,mat_ctx->vP,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
2459229984c5Sstefano_zampini   }
2460229984c5Sstefano_zampini 
24613425bc38SStefano Zampini   /* compute rhs for BDDC application */
24623425bc38SStefano Zampini   ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr);
24638eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
24643425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
2465229984c5Sstefano_zampini     if (mat_ctx->l2g_p) {
2466229984c5Sstefano_zampini       ierr = VecScale(mat_ctx->vP,-1.);CHKERRQ(ierr);
2467229984c5Sstefano_zampini       ierr = MatMultAdd(mat_ctx->Bt_BI,mat_ctx->vP,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr);
24683425bc38SStefano Zampini     }
2469229984c5Sstefano_zampini   }
2470229984c5Sstefano_zampini 
24713425bc38SStefano Zampini   /* apply BDDC */
2472580bdb30SBarry Smith   ierr = PetscArrayzero(pcbddc->benign_p0,pcbddc->benign_n);CHKERRQ(ierr);
2473dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
2474229984c5Sstefano_zampini 
2475229984c5Sstefano_zampini   /* put values into global vector */
2476af140850Sstefano_zampini   if (pcbddc->ChangeOfBasisMatrix) work = pcbddc->work_change;
2477af140850Sstefano_zampini   else work = standard_sol;
2478229984c5Sstefano_zampini   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2479229984c5Sstefano_zampini   ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
24808eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
24813425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
24823425bc38SStefano Zampini     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr);
248300f6b531SStefano Zampini     ierr = VecAYPX(pcis->vec1_D,-1.0,mat_ctx->temp_solution_D);CHKERRQ(ierr);
248400f6b531SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr);
2485c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
24863425bc38SStefano Zampini   }
2487229984c5Sstefano_zampini 
2488229984c5Sstefano_zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2489229984c5Sstefano_zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2490266e20e9SStefano Zampini   /* add p0 solution to final solution */
2491229984c5Sstefano_zampini   ierr = PCBDDCBenignGetOrSetP0(mat_ctx->pc,work,PETSC_FALSE);CHKERRQ(ierr);
2492fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2493af140850Sstefano_zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,work,standard_sol);CHKERRQ(ierr);
2494fc17d649SStefano Zampini   }
2495af140850Sstefano_zampini   ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr);
2496af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
2497229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2498229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2499229984c5Sstefano_zampini   }
25003425bc38SStefano Zampini   PetscFunctionReturn(0);
25013425bc38SStefano Zampini }
25021e6b0712SBarry Smith 
25035a1e936bSStefano Zampini static PetscErrorCode PCView_BDDCIPC(PC pc, PetscViewer viewer)
25045a1e936bSStefano Zampini {
25055a1e936bSStefano Zampini   PetscErrorCode ierr;
25065a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25075a1e936bSStefano Zampini   PetscBool      isascii;
25085a1e936bSStefano Zampini 
25095a1e936bSStefano Zampini   PetscFunctionBegin;
25105a1e936bSStefano Zampini   ierr = PCShellGetContext(pc,(void **)&bddcipc_ctx);CHKERRQ(ierr);
25115a1e936bSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
25125a1e936bSStefano Zampini   if (isascii) {
25135a1e936bSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"BDDC interface preconditioner\n");CHKERRQ(ierr);
25145a1e936bSStefano Zampini   }
25155a1e936bSStefano Zampini   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
25165a1e936bSStefano Zampini   ierr = PCView(bddcipc_ctx->bddc,viewer);CHKERRQ(ierr);
25175a1e936bSStefano Zampini   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
25185a1e936bSStefano Zampini   PetscFunctionReturn(0);
25195a1e936bSStefano Zampini }
25205a1e936bSStefano Zampini 
25215a1e936bSStefano Zampini static PetscErrorCode PCSetUp_BDDCIPC(PC pc)
25225a1e936bSStefano Zampini {
25235a1e936bSStefano Zampini   PetscErrorCode ierr;
25245a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25255a1e936bSStefano Zampini   PetscBool      isbddc;
25265a1e936bSStefano Zampini   Vec            vv;
25275a1e936bSStefano Zampini   IS             is;
25285a1e936bSStefano Zampini   PC_IS          *pcis;
25295a1e936bSStefano Zampini 
25305a1e936bSStefano Zampini   PetscFunctionBegin;
25315a1e936bSStefano Zampini   ierr = PCShellGetContext(pc,(void **)&bddcipc_ctx);CHKERRQ(ierr);
25325a1e936bSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)bddcipc_ctx->bddc,PCBDDC,&isbddc);CHKERRQ(ierr);
25335a1e936bSStefano Zampini   if (!isbddc) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid type %s. Must be of type bddc",((PetscObject)bddcipc_ctx->bddc)->type_name);
25345a1e936bSStefano Zampini   ierr = PCSetUp(bddcipc_ctx->bddc);CHKERRQ(ierr);
25355a1e936bSStefano Zampini 
25365a1e936bSStefano Zampini   /* create interface scatter */
25375a1e936bSStefano Zampini   pcis = (PC_IS*)(bddcipc_ctx->bddc->data);
25385a1e936bSStefano Zampini   ierr = VecScatterDestroy(&bddcipc_ctx->g2l);CHKERRQ(ierr);
25395a1e936bSStefano Zampini   ierr = MatCreateVecs(pc->pmat,&vv,NULL);CHKERRQ(ierr);
25405a1e936bSStefano Zampini   ierr = ISRenumber(pcis->is_B_global,NULL,NULL,&is);CHKERRQ(ierr);
25419448b7f1SJunchao Zhang   ierr = VecScatterCreate(vv,is,pcis->vec1_B,NULL,&bddcipc_ctx->g2l);CHKERRQ(ierr);
25425a1e936bSStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
25435a1e936bSStefano Zampini   ierr = VecDestroy(&vv);CHKERRQ(ierr);
25445a1e936bSStefano Zampini   PetscFunctionReturn(0);
25455a1e936bSStefano Zampini }
25465a1e936bSStefano Zampini 
25475a1e936bSStefano Zampini static PetscErrorCode PCApply_BDDCIPC(PC pc, Vec r, Vec x)
25485a1e936bSStefano Zampini {
25495a1e936bSStefano Zampini   PetscErrorCode ierr;
25505a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25515a1e936bSStefano Zampini   PC_IS          *pcis;
25525a1e936bSStefano Zampini   VecScatter     tmps;
25535a1e936bSStefano Zampini 
25545a1e936bSStefano Zampini   PetscFunctionBegin;
25555a1e936bSStefano Zampini   ierr = PCShellGetContext(pc,(void **)&bddcipc_ctx);CHKERRQ(ierr);
25565a1e936bSStefano Zampini   pcis = (PC_IS*)(bddcipc_ctx->bddc->data);
25575a1e936bSStefano Zampini   tmps = pcis->global_to_B;
25585a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
25595a1e936bSStefano Zampini   ierr = PCBDDCScalingRestriction(bddcipc_ctx->bddc,r,pcis->vec1_B);CHKERRQ(ierr);
25605a1e936bSStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc,PETSC_FALSE);CHKERRQ(ierr);
25615a1e936bSStefano Zampini   ierr = PCBDDCScalingExtension(bddcipc_ctx->bddc,pcis->vec1_B,x);CHKERRQ(ierr);
25625a1e936bSStefano Zampini   pcis->global_to_B = tmps;
25635a1e936bSStefano Zampini   PetscFunctionReturn(0);
25645a1e936bSStefano Zampini }
25655a1e936bSStefano Zampini 
25665a1e936bSStefano Zampini static PetscErrorCode PCApplyTranspose_BDDCIPC(PC pc, Vec r, Vec x)
25675a1e936bSStefano Zampini {
25685a1e936bSStefano Zampini   PetscErrorCode ierr;
25695a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25705a1e936bSStefano Zampini   PC_IS          *pcis;
25715a1e936bSStefano Zampini   VecScatter     tmps;
25725a1e936bSStefano Zampini 
25735a1e936bSStefano Zampini   PetscFunctionBegin;
25745a1e936bSStefano Zampini   ierr = PCShellGetContext(pc,(void **)&bddcipc_ctx);CHKERRQ(ierr);
25755a1e936bSStefano Zampini   pcis = (PC_IS*)(bddcipc_ctx->bddc->data);
25765a1e936bSStefano Zampini   tmps = pcis->global_to_B;
25775a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
25785a1e936bSStefano Zampini   ierr = PCBDDCScalingRestriction(bddcipc_ctx->bddc,r,pcis->vec1_B);CHKERRQ(ierr);
25795a1e936bSStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc,PETSC_TRUE);CHKERRQ(ierr);
25805a1e936bSStefano Zampini   ierr = PCBDDCScalingExtension(bddcipc_ctx->bddc,pcis->vec1_B,x);CHKERRQ(ierr);
25815a1e936bSStefano Zampini   pcis->global_to_B = tmps;
25825a1e936bSStefano Zampini   PetscFunctionReturn(0);
25835a1e936bSStefano Zampini }
25845a1e936bSStefano Zampini 
25855a1e936bSStefano Zampini static PetscErrorCode PCDestroy_BDDCIPC(PC pc)
25865a1e936bSStefano Zampini {
25875a1e936bSStefano Zampini   PetscErrorCode ierr;
25885a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25895a1e936bSStefano Zampini 
25905a1e936bSStefano Zampini   PetscFunctionBegin;
25915a1e936bSStefano Zampini   ierr = PCShellGetContext(pc,(void **)&bddcipc_ctx);CHKERRQ(ierr);
25925a1e936bSStefano Zampini   ierr = PCDestroy(&bddcipc_ctx->bddc);CHKERRQ(ierr);
25935a1e936bSStefano Zampini   ierr = VecScatterDestroy(&bddcipc_ctx->g2l);CHKERRQ(ierr);
25945a1e936bSStefano Zampini   ierr = PetscFree(bddcipc_ctx);CHKERRQ(ierr);
25955a1e936bSStefano Zampini   PetscFunctionReturn(0);
25965a1e936bSStefano Zampini }
25975a1e936bSStefano Zampini 
25983425bc38SStefano Zampini /*@
25990f202f7eSStefano Zampini  PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system
26003425bc38SStefano Zampini 
26013425bc38SStefano Zampini    Collective
26023425bc38SStefano Zampini 
26033425bc38SStefano Zampini    Input Parameters:
26040f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators
26050f202f7eSStefano Zampini -  fetidp_flux_sol - the solution of the FETI-DP linear system
26063425bc38SStefano Zampini 
26073425bc38SStefano Zampini    Output Parameters:
26080f202f7eSStefano Zampini .  standard_sol    - the solution defined on the physical domain
26093425bc38SStefano Zampini 
26103425bc38SStefano Zampini    Level: developer
26113425bc38SStefano Zampini 
26123425bc38SStefano Zampini    Notes:
26133425bc38SStefano Zampini 
26140f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetRHS
26153425bc38SStefano Zampini @*/
26163425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
26173425bc38SStefano Zampini {
2618674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
26193425bc38SStefano Zampini   PetscErrorCode ierr;
26203425bc38SStefano Zampini 
26213425bc38SStefano Zampini   PetscFunctionBegin;
2622266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1);
2623266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_sol,VEC_CLASSID,2);
2624266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_sol,VEC_CLASSID,3);
26253425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
2626163d334eSBarry Smith   ierr = PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr);
26273425bc38SStefano Zampini   PetscFunctionReturn(0);
26283425bc38SStefano Zampini }
26291e6b0712SBarry Smith 
2630547c9a8eSstefano_zampini static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, PetscBool fully_redundant, const char* prefix, Mat *fetidp_mat, PC *fetidp_pc)
26313425bc38SStefano Zampini {
2632674ae819SStefano Zampini 
2633674ae819SStefano Zampini   FETIDPMat_ctx  fetidpmat_ctx;
26343425bc38SStefano Zampini   Mat            newmat;
2635674ae819SStefano Zampini   FETIDPPC_ctx   fetidppc_ctx;
26363425bc38SStefano Zampini   PC             newpc;
2637ce94432eSBarry Smith   MPI_Comm       comm;
26383425bc38SStefano Zampini   PetscErrorCode ierr;
26393425bc38SStefano Zampini 
26403425bc38SStefano Zampini   PetscFunctionBegin;
2641ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
264215579a77SStefano Zampini   /* FETI-DP matrix */
26433425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr);
26441720468bSStefano Zampini   fetidpmat_ctx->fully_redundant = fully_redundant;
26453425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr);
2646a5bb87b3Sstefano_zampini   ierr = MatCreateShell(comm,fetidpmat_ctx->n,fetidpmat_ctx->n,fetidpmat_ctx->N,fetidpmat_ctx->N,fetidpmat_ctx,&newmat);CHKERRQ(ierr);
264715579a77SStefano Zampini   ierr = PetscObjectSetName((PetscObject)newmat,!fetidpmat_ctx->l2g_lambda_only ? "F" : "G");CHKERRQ(ierr);
26483425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr);
2649edf7251bSStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT_TRANSPOSE,(void (*)(void))FETIDPMatMultTranspose);CHKERRQ(ierr);
26503425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr);
265115579a77SStefano Zampini   /* propagate MatOptions */
265215579a77SStefano Zampini   {
265315579a77SStefano Zampini     PC_BDDC   *pcbddc = (PC_BDDC*)fetidpmat_ctx->pc->data;
265415579a77SStefano Zampini     PetscBool issym;
265515579a77SStefano Zampini 
265615579a77SStefano Zampini     ierr = MatGetOption(pc->mat,MAT_SYMMETRIC,&issym);CHKERRQ(ierr);
265715579a77SStefano Zampini     if (issym || pcbddc->symmetric_primal) {
265815579a77SStefano Zampini       ierr = MatSetOption(newmat,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
265915579a77SStefano Zampini     }
266015579a77SStefano Zampini   }
2661547c9a8eSstefano_zampini   ierr = MatSetOptionsPrefix(newmat,prefix);CHKERRQ(ierr);
2662547c9a8eSstefano_zampini   ierr = MatAppendOptionsPrefix(newmat,"fetidp_");CHKERRQ(ierr);
26633425bc38SStefano Zampini   ierr = MatSetUp(newmat);CHKERRQ(ierr);
266415579a77SStefano Zampini   /* FETI-DP preconditioner */
26653425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr);
26663425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr);
26673425bc38SStefano Zampini   ierr = PCCreate(comm,&newpc);CHKERRQ(ierr);
2668e1214c54Sstefano_zampini   ierr = PCSetOperators(newpc,newmat,newmat);CHKERRQ(ierr);
2669e1214c54Sstefano_zampini   ierr = PCSetOptionsPrefix(newpc,prefix);CHKERRQ(ierr);
2670e1214c54Sstefano_zampini   ierr = PCAppendOptionsPrefix(newpc,"fetidp_");CHKERRQ(ierr);
2671399ffe99SStefano Zampini   ierr = PCSetErrorIfFailure(newpc,pc->erroriffailure);CHKERRQ(ierr);
267215579a77SStefano Zampini   if (!fetidpmat_ctx->l2g_lambda_only) { /* standard FETI-DP */
26733425bc38SStefano Zampini     ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
267415579a77SStefano Zampini     ierr = PCShellSetName(newpc,"FETI-DP multipliers");CHKERRQ(ierr);
26753425bc38SStefano Zampini     ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr);
26763425bc38SStefano Zampini     ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr);
2677edf7251bSStefano Zampini     ierr = PCShellSetApplyTranspose(newpc,FETIDPPCApplyTranspose);CHKERRQ(ierr);
2678c45b8d2dSstefano_zampini     ierr = PCShellSetView(newpc,FETIDPPCView);CHKERRQ(ierr);
26793425bc38SStefano Zampini     ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
26805a1e936bSStefano Zampini   } else { /* saddle-point FETI-DP */
26815a1e936bSStefano Zampini     Mat       M;
26825a1e936bSStefano Zampini     PetscInt  psize;
26835a1e936bSStefano Zampini     PetscBool fake = PETSC_FALSE, isfieldsplit;
2684e1214c54Sstefano_zampini 
268515579a77SStefano Zampini     ierr = ISViewFromOptions(fetidpmat_ctx->lagrange,NULL,"-lag_view");CHKERRQ(ierr);
268615579a77SStefano Zampini     ierr = ISViewFromOptions(fetidpmat_ctx->pressure,NULL,"-press_view");CHKERRQ(ierr);
2687e1214c54Sstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_PPmat",(PetscObject*)&M);CHKERRQ(ierr);
2688e1214c54Sstefano_zampini     ierr = PCSetType(newpc,PCFIELDSPLIT);CHKERRQ(ierr);
2689e1214c54Sstefano_zampini     ierr = PCFieldSplitSetIS(newpc,"lag",fetidpmat_ctx->lagrange);CHKERRQ(ierr);
2690e1214c54Sstefano_zampini     ierr = PCFieldSplitSetIS(newpc,"p",fetidpmat_ctx->pressure);CHKERRQ(ierr);
2691e1214c54Sstefano_zampini     ierr = PCFieldSplitSetType(newpc,PC_COMPOSITE_SCHUR);CHKERRQ(ierr);
269240c75d76SStefano Zampini     ierr = PCFieldSplitSetSchurFactType(newpc,PC_FIELDSPLIT_SCHUR_FACT_DIAG);CHKERRQ(ierr);
26935a1e936bSStefano Zampini     ierr = ISGetSize(fetidpmat_ctx->pressure,&psize);CHKERRQ(ierr);
26945a1e936bSStefano Zampini     if (psize != M->rmap->N) {
26955a1e936bSStefano Zampini       Mat      M2;
26965a1e936bSStefano Zampini       PetscInt lpsize;
26975a1e936bSStefano Zampini 
26985a1e936bSStefano Zampini       fake = PETSC_TRUE;
26995a1e936bSStefano Zampini       ierr = ISGetLocalSize(fetidpmat_ctx->pressure,&lpsize);CHKERRQ(ierr);
27005a1e936bSStefano Zampini       ierr = MatCreate(comm,&M2);CHKERRQ(ierr);
27015a1e936bSStefano Zampini       ierr = MatSetType(M2,MATAIJ);CHKERRQ(ierr);
27025a1e936bSStefano Zampini       ierr = MatSetSizes(M2,lpsize,lpsize,psize,psize);CHKERRQ(ierr);
27035a1e936bSStefano Zampini       ierr = MatSetUp(M2);CHKERRQ(ierr);
27045a1e936bSStefano Zampini       ierr = MatAssemblyBegin(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27055a1e936bSStefano Zampini       ierr = MatAssemblyEnd(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27065a1e936bSStefano Zampini       ierr = PCFieldSplitSetSchurPre(newpc,PC_FIELDSPLIT_SCHUR_PRE_USER,M2);CHKERRQ(ierr);
27075a1e936bSStefano Zampini       ierr = MatDestroy(&M2);CHKERRQ(ierr);
27085a1e936bSStefano Zampini     } else {
2709e1214c54Sstefano_zampini       ierr = PCFieldSplitSetSchurPre(newpc,PC_FIELDSPLIT_SCHUR_PRE_USER,M);CHKERRQ(ierr);
27105a1e936bSStefano Zampini     }
2711c096484dSStefano Zampini     ierr = PCFieldSplitSetSchurScale(newpc,1.0);CHKERRQ(ierr);
271215579a77SStefano Zampini 
271315579a77SStefano Zampini     /* we need to setfromoptions and setup here to access the blocks */
2714e1214c54Sstefano_zampini     ierr = PCSetFromOptions(newpc);CHKERRQ(ierr);
2715e1214c54Sstefano_zampini     ierr = PCSetUp(newpc);CHKERRQ(ierr);
2716e1214c54Sstefano_zampini 
27175a1e936bSStefano Zampini     /* user may have changed the type (e.g. -fetidp_pc_type none) */
27185a1e936bSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)newpc,PCFIELDSPLIT,&isfieldsplit);CHKERRQ(ierr);
27195a1e936bSStefano Zampini     if (isfieldsplit) {
27205a1e936bSStefano Zampini       KSP       *ksps;
27215a1e936bSStefano Zampini       PC        ppc,lagpc;
27225a1e936bSStefano Zampini       PetscInt  nn;
2723064a4176SStefano Zampini       PetscBool ismatis,matisok = PETSC_FALSE,check = PETSC_FALSE;
27245a1e936bSStefano Zampini 
2725e1214c54Sstefano_zampini       /* set the solver for the (0,0) block */
27265a1e936bSStefano Zampini       ierr = PCFieldSplitSchurGetSubKSP(newpc,&nn,&ksps);CHKERRQ(ierr);
27275a1e936bSStefano Zampini       if (!nn) { /* not of type PC_COMPOSITE_SCHUR */
272840c75d76SStefano Zampini         ierr = PCFieldSplitGetSubKSP(newpc,&nn,&ksps);CHKERRQ(ierr);
27295a1e936bSStefano Zampini         if (!fake) { /* pass pmat to the pressure solver */
27305a1e936bSStefano Zampini           Mat F;
27315a1e936bSStefano Zampini 
27325a1e936bSStefano Zampini           ierr = KSPGetOperators(ksps[1],&F,NULL);CHKERRQ(ierr);
27335a1e936bSStefano Zampini           ierr = KSPSetOperators(ksps[1],F,M);CHKERRQ(ierr);
27345a1e936bSStefano Zampini         }
27355a1e936bSStefano Zampini       } else {
27365a1e936bSStefano Zampini         PetscBool issym;
27375a1e936bSStefano Zampini         Mat       S;
27385a1e936bSStefano Zampini 
27395a1e936bSStefano Zampini         ierr = PCFieldSplitSchurGetS(newpc,&S);CHKERRQ(ierr);
27405a1e936bSStefano Zampini 
27415a1e936bSStefano Zampini         ierr = MatGetOption(newmat,MAT_SYMMETRIC,&issym);CHKERRQ(ierr);
27425a1e936bSStefano Zampini         if (issym) {
27435a1e936bSStefano Zampini           ierr = MatSetOption(S,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
27445a1e936bSStefano Zampini         }
27455a1e936bSStefano Zampini       }
27465a1e936bSStefano Zampini       ierr = KSPGetPC(ksps[0],&lagpc);CHKERRQ(ierr);
2747e1214c54Sstefano_zampini       ierr = PCSetType(lagpc,PCSHELL);CHKERRQ(ierr);
27485a1e936bSStefano Zampini       ierr = PCShellSetName(lagpc,"FETI-DP multipliers");CHKERRQ(ierr);
2749e1214c54Sstefano_zampini       ierr = PCShellSetContext(lagpc,fetidppc_ctx);CHKERRQ(ierr);
2750e1214c54Sstefano_zampini       ierr = PCShellSetApply(lagpc,FETIDPPCApply);CHKERRQ(ierr);
2751e1214c54Sstefano_zampini       ierr = PCShellSetApplyTranspose(lagpc,FETIDPPCApplyTranspose);CHKERRQ(ierr);
2752e1214c54Sstefano_zampini       ierr = PCShellSetView(lagpc,FETIDPPCView);CHKERRQ(ierr);
2753e1214c54Sstefano_zampini       ierr = PCShellSetDestroy(lagpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
27545a1e936bSStefano Zampini 
27555a1e936bSStefano Zampini       /* Olof's idea: interface Schur complement preconditioner for the mass matrix */
27565a1e936bSStefano Zampini       ierr = KSPGetPC(ksps[1],&ppc);CHKERRQ(ierr);
27575a1e936bSStefano Zampini       if (fake) {
27585a1e936bSStefano Zampini         BDDCIPC_ctx    bddcipc_ctx;
2759ff11fd76SStefano Zampini         PetscContainer c;
27605a1e936bSStefano Zampini 
27615a1e936bSStefano Zampini         matisok = PETSC_TRUE;
27625a1e936bSStefano Zampini 
27635a1e936bSStefano Zampini         /* create inner BDDC solver */
27645a1e936bSStefano Zampini         ierr = PetscNew(&bddcipc_ctx);CHKERRQ(ierr);
27655a1e936bSStefano Zampini         ierr = PCCreate(comm,&bddcipc_ctx->bddc);CHKERRQ(ierr);
27665a1e936bSStefano Zampini         ierr = PCSetType(bddcipc_ctx->bddc,PCBDDC);CHKERRQ(ierr);
27675a1e936bSStefano Zampini         ierr = PCSetOperators(bddcipc_ctx->bddc,M,M);CHKERRQ(ierr);
2768ff11fd76SStefano Zampini         ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_pCSR",(PetscObject*)&c);CHKERRQ(ierr);
2769ff11fd76SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)M,MATIS,&ismatis);CHKERRQ(ierr);
2770ff11fd76SStefano Zampini         if (c && ismatis) {
2771ff11fd76SStefano Zampini           Mat      lM;
2772ff11fd76SStefano Zampini           PetscInt *csr,n;
2773ff11fd76SStefano Zampini 
2774ff11fd76SStefano Zampini           ierr = MatISGetLocalMat(M,&lM);CHKERRQ(ierr);
2775ff11fd76SStefano Zampini           ierr = MatGetSize(lM,&n,NULL);CHKERRQ(ierr);
2776ff11fd76SStefano Zampini           ierr = PetscContainerGetPointer(c,(void**)&csr);CHKERRQ(ierr);
2777ff11fd76SStefano Zampini           ierr = PCBDDCSetLocalAdjacencyGraph(bddcipc_ctx->bddc,n,csr,csr + (n + 1),PETSC_COPY_VALUES);CHKERRQ(ierr);
2778ff11fd76SStefano Zampini           ierr = MatISRestoreLocalMat(M,&lM);CHKERRQ(ierr);
2779ff11fd76SStefano Zampini         }
27805a1e936bSStefano Zampini         ierr = PCSetOptionsPrefix(bddcipc_ctx->bddc,((PetscObject)ksps[1])->prefix);CHKERRQ(ierr);
27815a1e936bSStefano Zampini         ierr = PCSetErrorIfFailure(bddcipc_ctx->bddc,pc->erroriffailure);CHKERRQ(ierr);
27825a1e936bSStefano Zampini         ierr = PCSetFromOptions(bddcipc_ctx->bddc);CHKERRQ(ierr);
27835a1e936bSStefano Zampini 
27845a1e936bSStefano Zampini         /* wrap the interface application */
27855a1e936bSStefano Zampini         ierr = PCSetType(ppc,PCSHELL);CHKERRQ(ierr);
27865a1e936bSStefano Zampini         ierr = PCShellSetName(ppc,"FETI-DP pressure");CHKERRQ(ierr);
27875a1e936bSStefano Zampini         ierr = PCShellSetContext(ppc,bddcipc_ctx);CHKERRQ(ierr);
27885a1e936bSStefano Zampini         ierr = PCShellSetSetUp(ppc,PCSetUp_BDDCIPC);CHKERRQ(ierr);
27895a1e936bSStefano Zampini         ierr = PCShellSetApply(ppc,PCApply_BDDCIPC);CHKERRQ(ierr);
27905a1e936bSStefano Zampini         ierr = PCShellSetApplyTranspose(ppc,PCApplyTranspose_BDDCIPC);CHKERRQ(ierr);
27915a1e936bSStefano Zampini         ierr = PCShellSetView(ppc,PCView_BDDCIPC);CHKERRQ(ierr);
27925a1e936bSStefano Zampini         ierr = PCShellSetDestroy(ppc,PCDestroy_BDDCIPC);CHKERRQ(ierr);
27935a1e936bSStefano Zampini       }
27945a1e936bSStefano Zampini 
27955a1e936bSStefano Zampini       /* determine if we need to assemble M to construct a preconditioner */
27965a1e936bSStefano Zampini       if (!matisok) {
27975a1e936bSStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)M,MATIS,&ismatis);CHKERRQ(ierr);
27985a1e936bSStefano Zampini         ierr = PetscObjectTypeCompareAny((PetscObject)ppc,&matisok,PCBDDC,PCJACOBI,PCNONE,PCMG,"");CHKERRQ(ierr);
27995a1e936bSStefano Zampini         if (ismatis && !matisok) {
28005a1e936bSStefano Zampini           ierr = MatConvert(M,MATAIJ,MAT_INPLACE_MATRIX,&M);CHKERRQ(ierr);
28015a1e936bSStefano Zampini         }
28025a1e936bSStefano Zampini       }
2803064a4176SStefano Zampini 
2804064a4176SStefano Zampini       /* run the subproblems to check convergence */
2805064a4176SStefano Zampini       ierr = PetscOptionsGetBool(NULL,((PetscObject)newmat)->prefix,"-check_saddlepoint",&check,NULL);CHKERRQ(ierr);
2806064a4176SStefano Zampini       if (check) {
2807064a4176SStefano Zampini         PetscInt i;
2808064a4176SStefano Zampini 
2809064a4176SStefano Zampini         for (i=0;i<nn;i++) {
2810064a4176SStefano Zampini           KSP       kspC;
2811064a4176SStefano Zampini           PC        pc;
2812064a4176SStefano Zampini           Mat       F,pF;
2813064a4176SStefano Zampini           Vec       x,y;
2814064a4176SStefano Zampini           PetscBool isschur,prec = PETSC_TRUE;
2815064a4176SStefano Zampini 
2816064a4176SStefano Zampini           ierr = KSPCreate(PetscObjectComm((PetscObject)ksps[i]),&kspC);CHKERRQ(ierr);
2817064a4176SStefano Zampini           ierr = KSPSetOptionsPrefix(kspC,((PetscObject)ksps[i])->prefix);CHKERRQ(ierr);
2818064a4176SStefano Zampini           ierr = KSPAppendOptionsPrefix(kspC,"check_");CHKERRQ(ierr);
2819064a4176SStefano Zampini           ierr = KSPGetOperators(ksps[i],&F,&pF);CHKERRQ(ierr);
2820064a4176SStefano Zampini           ierr = PetscObjectTypeCompare((PetscObject)F,MATSCHURCOMPLEMENT,&isschur);CHKERRQ(ierr);
2821064a4176SStefano Zampini           if (isschur) {
2822064a4176SStefano Zampini             KSP  kspS,kspS2;
2823064a4176SStefano Zampini             Mat  A00,pA00,A10,A01,A11;
2824064a4176SStefano Zampini             char prefix[256];
2825064a4176SStefano Zampini 
2826064a4176SStefano Zampini             ierr = MatSchurComplementGetKSP(F,&kspS);CHKERRQ(ierr);
2827064a4176SStefano Zampini             ierr = MatSchurComplementGetSubMatrices(F,&A00,&pA00,&A01,&A10,&A11);CHKERRQ(ierr);
2828064a4176SStefano Zampini             ierr = MatCreateSchurComplement(A00,pA00,A01,A10,A11,&F);CHKERRQ(ierr);
2829064a4176SStefano Zampini             ierr = MatSchurComplementGetKSP(F,&kspS2);CHKERRQ(ierr);
2830064a4176SStefano Zampini             ierr = PetscSNPrintf(prefix,sizeof(prefix),"%sschur_",((PetscObject)kspC)->prefix);CHKERRQ(ierr);
2831064a4176SStefano Zampini             ierr = KSPSetOptionsPrefix(kspS2,prefix);CHKERRQ(ierr);
2832064a4176SStefano Zampini             ierr = KSPGetPC(kspS2,&pc);CHKERRQ(ierr);
2833064a4176SStefano Zampini             ierr = PCSetType(pc,PCKSP);CHKERRQ(ierr);
2834064a4176SStefano Zampini             ierr = PCKSPSetKSP(pc,kspS);CHKERRQ(ierr);
2835064a4176SStefano Zampini             ierr = KSPSetFromOptions(kspS2);CHKERRQ(ierr);
2836064a4176SStefano Zampini             ierr = KSPGetPC(kspS2,&pc);CHKERRQ(ierr);
2837064a4176SStefano Zampini             ierr = PCSetUseAmat(pc,PETSC_TRUE);CHKERRQ(ierr);
2838064a4176SStefano Zampini           } else {
2839064a4176SStefano Zampini             ierr = PetscObjectReference((PetscObject)F);CHKERRQ(ierr);
2840064a4176SStefano Zampini           }
2841064a4176SStefano Zampini           ierr = KSPSetFromOptions(kspC);CHKERRQ(ierr);
2842064a4176SStefano Zampini           ierr = PetscOptionsGetBool(NULL,((PetscObject)kspC)->prefix,"-preconditioned",&prec,NULL);CHKERRQ(ierr);
2843064a4176SStefano Zampini           if (prec)  {
2844064a4176SStefano Zampini             ierr = KSPGetPC(ksps[i],&pc);CHKERRQ(ierr);
2845064a4176SStefano Zampini             ierr = KSPSetPC(kspC,pc);CHKERRQ(ierr);
2846064a4176SStefano Zampini           }
2847064a4176SStefano Zampini           ierr = KSPSetOperators(kspC,F,pF);CHKERRQ(ierr);
2848064a4176SStefano Zampini           ierr = MatCreateVecs(F,&x,&y);CHKERRQ(ierr);
2849064a4176SStefano Zampini           ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
2850064a4176SStefano Zampini           ierr = MatMult(F,x,y);CHKERRQ(ierr);
2851064a4176SStefano Zampini           ierr = KSPSolve(kspC,y,x);CHKERRQ(ierr);
2852c0decd05SBarry Smith           ierr = KSPCheckSolve(kspC,pc,x);CHKERRQ(ierr);
2853064a4176SStefano Zampini           ierr = KSPDestroy(&kspC);CHKERRQ(ierr);
2854064a4176SStefano Zampini           ierr = MatDestroy(&F);CHKERRQ(ierr);
2855064a4176SStefano Zampini           ierr = VecDestroy(&x);CHKERRQ(ierr);
2856064a4176SStefano Zampini           ierr = VecDestroy(&y);CHKERRQ(ierr);
2857064a4176SStefano Zampini         }
2858064a4176SStefano Zampini       }
2859e1214c54Sstefano_zampini       ierr = PetscFree(ksps);CHKERRQ(ierr);
2860e1214c54Sstefano_zampini     }
28615a1e936bSStefano Zampini   }
28623425bc38SStefano Zampini   /* return pointers for objects created */
28633425bc38SStefano Zampini   *fetidp_mat = newmat;
28643425bc38SStefano Zampini   *fetidp_pc  = newpc;
28653425bc38SStefano Zampini   PetscFunctionReturn(0);
28663425bc38SStefano Zampini }
28671e6b0712SBarry Smith 
286894ef8ddeSSatish Balay /*@C
28690f202f7eSStefano Zampini  PCBDDCCreateFETIDPOperators - Create FETI-DP operators
28703425bc38SStefano Zampini 
28713425bc38SStefano Zampini    Collective
28723425bc38SStefano Zampini 
28733425bc38SStefano Zampini    Input Parameters:
28741720468bSStefano Zampini +  pc - the BDDC preconditioning context (setup should have been called before)
2875547c9a8eSstefano_zampini .  fully_redundant - true for a fully redundant set of Lagrange multipliers
2876547c9a8eSstefano_zampini -  prefix - optional options database prefix for the objects to be created (can be NULL)
287728509bceSStefano Zampini 
287828509bceSStefano Zampini    Output Parameters:
28790f202f7eSStefano Zampini +  fetidp_mat - shell FETI-DP matrix object
28800f202f7eSStefano Zampini -  fetidp_pc  - shell Dirichlet preconditioner for FETI-DP matrix
288128509bceSStefano Zampini 
28823425bc38SStefano Zampini    Level: developer
28833425bc38SStefano Zampini 
28843425bc38SStefano Zampini    Notes:
28850f202f7eSStefano Zampini      Currently the only operations provided for FETI-DP matrix are MatMult and MatMultTranspose
28863425bc38SStefano Zampini 
28870f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCMatFETIDPGetRHS, PCBDDCMatFETIDPGetSolution
28883425bc38SStefano Zampini @*/
2889547c9a8eSstefano_zampini PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc)
28903425bc38SStefano Zampini {
28913425bc38SStefano Zampini   PetscErrorCode ierr;
28923425bc38SStefano Zampini 
28933425bc38SStefano Zampini   PetscFunctionBegin;
28943425bc38SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
28953425bc38SStefano Zampini   if (pc->setupcalled) {
2896547c9a8eSstefano_zampini     ierr = PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,PetscBool,const char*,Mat*,PC*),(pc,fully_redundant,prefix,fetidp_mat,fetidp_pc));CHKERRQ(ierr);
28976080607fSStefano Zampini   } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"You must call PCSetup_BDDC() first");
28983425bc38SStefano Zampini   PetscFunctionReturn(0);
28993425bc38SStefano Zampini }
29000c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
2901da1bb401SStefano Zampini /*MC
2902da1bb401SStefano Zampini    PCBDDC - Balancing Domain Decomposition by Constraints.
29030c7d97c5SJed Brown 
290428509bceSStefano Zampini    An implementation of the BDDC preconditioner based on
290528509bceSStefano Zampini 
290628509bceSStefano Zampini .vb
290728509bceSStefano Zampini    [1] C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
2908a8d69d7bSBarry Smith    [2] A. Klawonn and O. B. Widlund. "Dual-Primal FETI Methods for Linear Elasticity", https://cs.nyu.edu/dynamic/reports/?year=all
2909a8d69d7bSBarry Smith    [3] J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", https://arxiv.org/abs/0712.3977
29100f202f7eSStefano Zampini    [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
291128509bceSStefano Zampini .ve
291228509bceSStefano Zampini 
291328509bceSStefano Zampini    The matrix to be preconditioned (Pmat) must be of type MATIS.
291428509bceSStefano Zampini 
29150f202f7eSStefano Zampini    Currently works with MATIS matrices with local matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers.
291628509bceSStefano Zampini 
291728509bceSStefano Zampini    It also works with unsymmetric and indefinite problems.
291828509bceSStefano Zampini 
2919b6fdb6dfSStefano 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.
2920b6fdb6dfSStefano Zampini 
2921c7017625SStefano 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).
292228509bceSStefano Zampini 
29230f202f7eSStefano 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()
292430368db7SStefano Zampini    Additional information on dofs can be provided by using PCBDDCSetDofsSplitting(), PCBDDCSetDirichletBoundaries(), PCBDDCSetNeumannBoundaries(), and PCBDDCSetPrimalVerticesIS() and their local counterparts.
292528509bceSStefano Zampini 
29260f202f7eSStefano Zampini    Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). Non-singular modes are retained via SVD.
292728509bceSStefano Zampini 
29280f202f7eSStefano 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.
29290f202f7eSStefano Zampini    User defined change of basis can be passed to PCBDDC by using PCBDDCSetChangeOfBasisMat()
293028509bceSStefano Zampini 
29310f202f7eSStefano Zampini    The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using a MatPartitioning object.
293228509bceSStefano Zampini 
2933df4d28bfSStefano 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.
293428509bceSStefano Zampini 
29350f202f7eSStefano 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.
29360f202f7eSStefano Zampini    Deluxe scaling is not supported yet for FETI-DP.
29370f202f7eSStefano Zampini 
29380f202f7eSStefano Zampini    Options Database Keys (some of them, run with -h for a complete list):
29390f202f7eSStefano Zampini 
2940a2b725a8SWilliam Gropp +    -pc_bddc_use_vertices <true> - use or not vertices in primal space
29410f202f7eSStefano Zampini .    -pc_bddc_use_edges <true> - use or not edges in primal space
29420f202f7eSStefano Zampini .    -pc_bddc_use_faces <false> - use or not faces in primal space
29430f202f7eSStefano Zampini .    -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems
29440f202f7eSStefano Zampini .    -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only)
29450f202f7eSStefano Zampini .    -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested
29460f202f7eSStefano Zampini .    -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1])
294728509bceSStefano Zampini .    -pc_bddc_levels <0> - maximum number of levels for multilevel
29480f202f7eSStefano 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)
29495459c157SBarry 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)
29500f202f7eSStefano Zampini .    -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling
2951*71f2caa7Sprj- .    -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)
2952bd2a564bSStefano 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)
295328509bceSStefano Zampini -    -pc_bddc_check_level <0> - set verbosity level of debugging output
295428509bceSStefano Zampini 
295528509bceSStefano Zampini    Options for Dirichlet, Neumann or coarse solver can be set with
295628509bceSStefano Zampini .vb
295728509bceSStefano Zampini       -pc_bddc_dirichlet_
295828509bceSStefano Zampini       -pc_bddc_neumann_
295928509bceSStefano Zampini       -pc_bddc_coarse_
296028509bceSStefano Zampini .ve
2961f9ff08acSPierre Jolivet    e.g. -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. PCBDDC uses by default KSPPREONLY and PCLU.
296228509bceSStefano Zampini 
29630f202f7eSStefano Zampini    When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified as
296428509bceSStefano Zampini .vb
2965312be037SStefano Zampini       -pc_bddc_dirichlet_lN_
2966312be037SStefano Zampini       -pc_bddc_neumann_lN_
2967312be037SStefano Zampini       -pc_bddc_coarse_lN_
296828509bceSStefano Zampini .ve
29690f202f7eSStefano Zampini    Note that level number ranges from the finest (0) to the coarsest (N).
29700f202f7eSStefano 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.
29710f202f7eSStefano Zampini .vb
29720f202f7eSStefano Zampini      -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3
29730f202f7eSStefano Zampini .ve
29740f202f7eSStefano 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
2975da1bb401SStefano Zampini 
2976da1bb401SStefano Zampini    Level: intermediate
2977da1bb401SStefano Zampini 
2978e94cfbe0SPatrick Sanan    Developer Notes:
2979da1bb401SStefano Zampini 
2980da1bb401SStefano Zampini    Contributed by Stefano Zampini
2981da1bb401SStefano Zampini 
2982da1bb401SStefano Zampini .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
2983da1bb401SStefano Zampini M*/
2984b2573a8aSBarry Smith 
29858cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
2986da1bb401SStefano Zampini {
2987da1bb401SStefano Zampini   PetscErrorCode      ierr;
2988da1bb401SStefano Zampini   PC_BDDC             *pcbddc;
2989da1bb401SStefano Zampini 
2990da1bb401SStefano Zampini   PetscFunctionBegin;
2991b00a9115SJed Brown   ierr     = PetscNewLog(pc,&pcbddc);CHKERRQ(ierr);
2992da1bb401SStefano Zampini   pc->data = (void*)pcbddc;
2993da1bb401SStefano Zampini 
2994da1bb401SStefano Zampini   /* create PCIS data structure */
2995da1bb401SStefano Zampini   ierr = PCISCreate(pc);CHKERRQ(ierr);
2996da1bb401SStefano Zampini 
29979326c5c6Sstefano_zampini   /* create local graph structure */
29989326c5c6Sstefano_zampini   ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr);
29999326c5c6Sstefano_zampini 
30009326c5c6Sstefano_zampini   /* BDDC nonzero defaults */
30016d9e27e4SStefano Zampini   pcbddc->use_nnsp                  = PETSC_TRUE;
300208a5cf49SStefano Zampini   pcbddc->use_local_adj             = PETSC_TRUE;
300347d04d0dSStefano Zampini   pcbddc->use_vertices              = PETSC_TRUE;
300447d04d0dSStefano Zampini   pcbddc->use_edges                 = PETSC_TRUE;
30053301b35fSStefano Zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
300614f95afaSStefano Zampini   pcbddc->vertex_size               = 1;
3007c703fcc7SStefano Zampini   pcbddc->recompute_topography      = PETSC_TRUE;
300868457ee5SStefano Zampini   pcbddc->coarse_size               = -1;
300985c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
301047d04d0dSStefano Zampini   pcbddc->coarsening_ratio          = 8;
301157de7509SStefano Zampini   pcbddc->coarse_eqs_per_proc       = 1;
301227b6a85dSStefano Zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
30131e0482f5SStefano Zampini   pcbddc->nedfield                  = -1;
30141e0482f5SStefano Zampini   pcbddc->nedglobal                 = PETSC_TRUE;
3015be12c134Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
3016b96c3477SStefano Zampini   pcbddc->sub_schurs_layers         = -1;
3017bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[0]     = 0.0;
3018bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[1]     = 0.0;
3019b7eb3628SStefano Zampini 
3020da1bb401SStefano Zampini   /* function pointers */
3021da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
302293bd9ae7SStefano Zampini   pc->ops->applytranspose      = PCApplyTranspose_BDDC;
3023da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
3024da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
3025da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
30266b78500eSPatrick Sanan   pc->ops->view                = PCView_BDDC;
3027da1bb401SStefano Zampini   pc->ops->applyrichardson     = 0;
3028da1bb401SStefano Zampini   pc->ops->applysymmetricleft  = 0;
3029da1bb401SStefano Zampini   pc->ops->applysymmetricright = 0;
3030534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
3031534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
30329326c5c6Sstefano_zampini   pc->ops->reset               = PCReset_BDDC;
3033da1bb401SStefano Zampini 
3034da1bb401SStefano Zampini   /* composing function */
3035a13144ffSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",PCBDDCSetDiscreteGradient_BDDC);CHKERRQ(ierr);
3036a198735bSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",PCBDDCSetDivergenceMat_BDDC);CHKERRQ(ierr);
3037906d46d4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",PCBDDCSetChangeOfBasisMat_BDDC);CHKERRQ(ierr);
3038674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
303930368db7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",PCBDDCSetPrimalVerticesIS_BDDC);CHKERRQ(ierr);
30403100ebe3SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesLocalIS_C",PCBDDCGetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
30413100ebe3SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesIS_C",PCBDDCGetPrimalVerticesIS_BDDC);CHKERRQ(ierr);
3042bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr);
30432b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC);CHKERRQ(ierr);
3044b8ffe317SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC);CHKERRQ(ierr);
30452b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC);CHKERRQ(ierr);
3046bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
304782ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",PCBDDCSetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
3048bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
304982ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",PCBDDCSetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
3050bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
305182ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",PCBDDCGetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
3052bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
305382ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",PCBDDCGetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
3054bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
305563602bcaSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",PCBDDCSetDofsSplittingLocal_BDDC);CHKERRQ(ierr);
3056bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
3057bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr);
3058bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr);
3059bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr);
3060a06fd7f2SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",PCPreSolveChangeRHS_BDDC);CHKERRQ(ierr);
3061ab8c8b98SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",PCSetCoordinates_BDDC);CHKERRQ(ierr);
3062da1bb401SStefano Zampini   PetscFunctionReturn(0);
3063da1bb401SStefano Zampini }
306443371fb9SStefano Zampini 
306543371fb9SStefano Zampini /*@C
306643371fb9SStefano Zampini  PCBDDCInitializePackage - This function initializes everything in the PCBDDC package. It is called
30678a690491SBarry Smith     from PCInitializePackage().
306843371fb9SStefano Zampini 
306943371fb9SStefano Zampini  Level: developer
307043371fb9SStefano Zampini 
307143371fb9SStefano Zampini  .seealso: PetscInitialize()
307243371fb9SStefano Zampini @*/
307343371fb9SStefano Zampini PetscErrorCode PCBDDCInitializePackage(void)
307443371fb9SStefano Zampini {
307543371fb9SStefano Zampini   PetscErrorCode ierr;
307643371fb9SStefano Zampini   int            i;
307743371fb9SStefano Zampini 
307843371fb9SStefano Zampini   PetscFunctionBegin;
307943371fb9SStefano Zampini   if (PCBDDCPackageInitialized) PetscFunctionReturn(0);
308043371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_TRUE;
308143371fb9SStefano Zampini   ierr = PetscRegisterFinalize(PCBDDCFinalizePackage);CHKERRQ(ierr);
308243371fb9SStefano Zampini 
308343371fb9SStefano Zampini   /* general events */
308443371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCTopo",PC_CLASSID,&PC_BDDC_Topology[0]);CHKERRQ(ierr);
308543371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCLKSP",PC_CLASSID,&PC_BDDC_LocalSolvers[0]);CHKERRQ(ierr);
308643371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCLWor",PC_CLASSID,&PC_BDDC_LocalWork[0]);CHKERRQ(ierr);
308743371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCCorr",PC_CLASSID,&PC_BDDC_CorrectionSetUp[0]);CHKERRQ(ierr);
30888ead10e4SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCASet",PC_CLASSID,&PC_BDDC_ApproxSetUp[0]);CHKERRQ(ierr);
30898ead10e4SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCAApp",PC_CLASSID,&PC_BDDC_ApproxApply[0]);CHKERRQ(ierr);
309043371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCCSet",PC_CLASSID,&PC_BDDC_CoarseSetUp[0]);CHKERRQ(ierr);
309143371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCCKSP",PC_CLASSID,&PC_BDDC_CoarseSolver[0]);CHKERRQ(ierr);
309243371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCAdap",PC_CLASSID,&PC_BDDC_AdaptiveSetUp[0]);CHKERRQ(ierr);
309343371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCScal",PC_CLASSID,&PC_BDDC_Scaling[0]);CHKERRQ(ierr);
309443371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCSchr",PC_CLASSID,&PC_BDDC_Schurs[0]);CHKERRQ(ierr);
309543371fb9SStefano Zampini   for (i=1;i<PETSC_PCBDDC_MAXLEVELS;i++) {
309643371fb9SStefano Zampini     char ename[32];
309743371fb9SStefano Zampini 
309843371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCTopo l%02d",i);CHKERRQ(ierr);
309943371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Topology[i]);CHKERRQ(ierr);
310043371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCLKSP l%02d",i);CHKERRQ(ierr);
310143371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_LocalSolvers[i]);CHKERRQ(ierr);
310243371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCLWor l%02d",i);CHKERRQ(ierr);
310343371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_LocalWork[i]);CHKERRQ(ierr);
310443371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCCorr l%02d",i);CHKERRQ(ierr);
310543371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CorrectionSetUp[i]);CHKERRQ(ierr);
31068ead10e4SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCASet l%02d",i);CHKERRQ(ierr);
31078ead10e4SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_ApproxSetUp[i]);CHKERRQ(ierr);
31088ead10e4SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCAApp l%02d",i);CHKERRQ(ierr);
31098ead10e4SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_ApproxApply[i]);CHKERRQ(ierr);
311043371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCCSet l%02d",i);CHKERRQ(ierr);
311143371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CoarseSetUp[i]);CHKERRQ(ierr);
311243371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCCKSP l%02d",i);CHKERRQ(ierr);
311343371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CoarseSolver[i]);CHKERRQ(ierr);
311443371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCAdap l%02d",i);CHKERRQ(ierr);
311543371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_AdaptiveSetUp[i]);CHKERRQ(ierr);
311643371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCScal l%02d",i);CHKERRQ(ierr);
311743371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Scaling[i]);CHKERRQ(ierr);
311843371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCSchr l%02d",i);CHKERRQ(ierr);
311943371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Schurs[i]);CHKERRQ(ierr);
312043371fb9SStefano Zampini   }
312143371fb9SStefano Zampini   PetscFunctionReturn(0);
312243371fb9SStefano Zampini }
312343371fb9SStefano Zampini 
312443371fb9SStefano Zampini /*@C
312543371fb9SStefano Zampini  PCBDDCFinalizePackage - This function frees everything from the PCBDDC package. It is
312643371fb9SStefano Zampini     called from PetscFinalize() automatically.
312743371fb9SStefano Zampini 
312843371fb9SStefano Zampini  Level: developer
312943371fb9SStefano Zampini 
313043371fb9SStefano Zampini  .seealso: PetscFinalize()
313143371fb9SStefano Zampini @*/
313243371fb9SStefano Zampini PetscErrorCode PCBDDCFinalizePackage(void)
313343371fb9SStefano Zampini {
313443371fb9SStefano Zampini   PetscFunctionBegin;
313543371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_FALSE;
313643371fb9SStefano Zampini   PetscFunctionReturn(0);
313743371fb9SStefano Zampini }
3138