xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 4f819b78fd7111cd978c8a0a32997152d470e560)
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];
4743371fb9SStefano Zampini PetscLogEvent PC_BDDC_CoarseSetUp[PETSC_PCBDDC_MAXLEVELS];
4843371fb9SStefano Zampini PetscLogEvent PC_BDDC_CoarseSolver[PETSC_PCBDDC_MAXLEVELS];
4943371fb9SStefano Zampini PetscLogEvent PC_BDDC_AdaptiveSetUp[PETSC_PCBDDC_MAXLEVELS];
5043371fb9SStefano Zampini PetscLogEvent PC_BDDC_Scaling[PETSC_PCBDDC_MAXLEVELS];
5143371fb9SStefano Zampini PetscLogEvent PC_BDDC_Schurs[PETSC_PCBDDC_MAXLEVELS];
5243371fb9SStefano Zampini 
530369aaf7SStefano Zampini PetscErrorCode PCApply_BDDC(PC,Vec,Vec);
540369aaf7SStefano Zampini 
554416b707SBarry Smith PetscErrorCode PCSetFromOptions_BDDC(PetscOptionItems *PetscOptionsObject,PC pc)
560c7d97c5SJed Brown {
570c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
58e569e4e1SStefano Zampini   PetscInt       nt,i;
590c7d97c5SJed Brown   PetscErrorCode ierr;
600c7d97c5SJed Brown 
610c7d97c5SJed Brown   PetscFunctionBegin;
62e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"BDDC options");CHKERRQ(ierr);
638eeda7d8SStefano Zampini   /* Verbose debugging */
64a13144ffSStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_check_level","Verbose output for PCBDDC (intended for debug)","none",pcbddc->dbg_flag,&pcbddc->dbg_flag,NULL);CHKERRQ(ierr);
65a13144ffSStefano Zampini   /* Approximate solvers */
66c7017625SStefano 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);
67c7017625SStefano 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);
68c7017625SStefano 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);
69c7017625SStefano 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);
706b78500eSPatrick Sanan   /* Primal space customization */
7108a5cf49SStefano 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);
72be12c134Sstefano_zampini   ierr = PetscOptionsInt("-pc_bddc_graph_maxcount","Maximum number of shared subdomains for a connected component","none",pcbddc->graphmaxcount,&pcbddc->graphmaxcount,NULL);CHKERRQ(ierr);
731c7a958bSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_corner_selection","Activates face-based corner selection","none",pcbddc->corner_selection,&pcbddc->corner_selection,NULL);CHKERRQ(ierr);
748eeda7d8SStefano 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);
758eeda7d8SStefano 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);
768eeda7d8SStefano 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);
7714f95afaSStefano 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);
786661aa1dSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_true_nnsp","Use near null space attached to the matrix without modifications","none",pcbddc->use_nnsp_true,&pcbddc->use_nnsp_true,NULL);CHKERRQ(ierr);
7914f95afaSStefano 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);
808eeda7d8SStefano Zampini   /* Change of basis */
81b9b85e73SStefano 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);
82b9b85e73SStefano 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);
83674ae819SStefano Zampini   if (!pcbddc->use_change_of_basis) {
84674ae819SStefano Zampini     pcbddc->use_change_on_faces = PETSC_FALSE;
85674ae819SStefano Zampini   }
868eeda7d8SStefano Zampini   /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */
878eeda7d8SStefano 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);
88e569e4e1SStefano 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);
89e569e4e1SStefano Zampini   i    = pcbddc->coarsening_ratio;
90e569e4e1SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","PCBDDCSetCoarseningRatio",i,&i,NULL);CHKERRQ(ierr);
91e569e4e1SStefano Zampini   ierr = PCBDDCSetCoarseningRatio(pc,i);CHKERRQ(ierr);
92e569e4e1SStefano Zampini   i    = pcbddc->max_levels;
93e569e4e1SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_levels","Set maximum number of levels for multilevel","PCBDDCSetLevels",i,&i,NULL);CHKERRQ(ierr);
94e569e4e1SStefano Zampini   ierr = PCBDDCSetLevels(pc,i);CHKERRQ(ierr);
95e569e4e1SStefano 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);
96323d395dSStefano 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);
97674ae819SStefano 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);
98b96c3477SStefano 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);
99b96c3477SStefano 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);
100b96c3477SStefano 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);
101683d3df6SStefano 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);
102bf3a8328SStefano 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);
103839e9adbSstefano_zampini   ierr = PetscOptionsBool("-pc_bddc_deluxe_singlemat","Collapse deluxe operators","none",pcbddc->deluxe_singlemat,&pcbddc->deluxe_singlemat,NULL);CHKERRQ(ierr);
104bf3a8328SStefano 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);
105bd2a564bSStefano Zampini   nt   = 2;
106bd2a564bSStefano Zampini   ierr = PetscOptionsRealArray("-pc_bddc_adaptive_threshold","Thresholds to be used for adaptive selection of constraints","none",pcbddc->adaptive_threshold,&nt,NULL);CHKERRQ(ierr);
107bd2a564bSStefano Zampini   if (nt == 1) pcbddc->adaptive_threshold[1] = pcbddc->adaptive_threshold[0];
10808122e43SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_adaptive_nmin","Minimum number of constraints per connected components","none",pcbddc->adaptive_nmin,&pcbddc->adaptive_nmin,NULL);CHKERRQ(ierr);
10908122e43SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_adaptive_nmax","Maximum number of constraints per connected components","none",pcbddc->adaptive_nmax,&pcbddc->adaptive_nmax,NULL);CHKERRQ(ierr);
1103301b35fSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_symmetric","Symmetric computation of primal basis functions","none",pcbddc->symmetric_primal,&pcbddc->symmetric_primal,NULL);CHKERRQ(ierr);
111b0c7d250SStefano 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);
112b3afcdbeSStefano 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);
113e9627c49SStefano 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);
11427b6a85dSStefano 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);
115a198735bSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nonetflux","Automatic computation of no-net-flux quadrature weights","none",pcbddc->compute_nonetflux,&pcbddc->compute_nonetflux,NULL);CHKERRQ(ierr);
1164f1b2e48SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_detect_disconnected","Detects disconnected subdomains","none",pcbddc->detect_disconnected,&pcbddc->detect_disconnected,NULL);CHKERRQ(ierr);
1178361f951SStefano 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);
11870c64980SStefano 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);
1190c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
1200c7d97c5SJed Brown   PetscFunctionReturn(0);
1210c7d97c5SJed Brown }
1226b78500eSPatrick Sanan 
1236b78500eSPatrick Sanan static PetscErrorCode PCView_BDDC(PC pc,PetscViewer viewer)
1246b78500eSPatrick Sanan {
1256b78500eSPatrick Sanan   PC_BDDC              *pcbddc = (PC_BDDC*)pc->data;
126e9627c49SStefano Zampini   PC_IS                *pcis = (PC_IS*)pc->data;
1276b78500eSPatrick Sanan   PetscErrorCode       ierr;
12871783a16SStefano Zampini   PetscBool            isascii;
129e9627c49SStefano Zampini   PetscSubcomm         subcomm;
130e9627c49SStefano Zampini   PetscViewer          subviewer;
1316b78500eSPatrick Sanan 
1326b78500eSPatrick Sanan   PetscFunctionBegin;
1336b78500eSPatrick Sanan   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1346b78500eSPatrick Sanan   /* ASCII viewer */
1356b78500eSPatrick Sanan   if (isascii) {
1364b2aedd3SStefano Zampini     PetscMPIInt   color,rank,size;
137fbad9177SStefano Zampini     PetscInt64    loc[7],gsum[6],gmax[6],gmin[6],totbenign;
138e9627c49SStefano Zampini     PetscScalar   interface_size;
139e9627c49SStefano Zampini     PetscReal     ratio1=0.,ratio2=0.;
140e9627c49SStefano Zampini     Vec           counter;
1416b78500eSPatrick Sanan 
142b74ba07aSstefano_zampini     if (!pc->setupcalled) {
143b74ba07aSstefano_zampini       ierr = PetscViewerASCIIPrintf(viewer,"  Partial information available: preconditioner has not been setup yet\n");CHKERRQ(ierr);
144b74ba07aSstefano_zampini     }
145efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use verbose output: %D\n",pcbddc->dbg_flag);CHKERRQ(ierr);
1466f0c0a6aSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Use user-defined CSR: %d\n",!!pcbddc->mat_graph->nvtxs_csr);CHKERRQ(ierr);
1476f0c0a6aSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Use local mat graph: %d\n",pcbddc->use_local_adj && !pcbddc->mat_graph->nvtxs_csr);CHKERRQ(ierr);
148e9627c49SStefano Zampini     if (pcbddc->mat_graph->twodim) {
149efd4aadfSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Connectivity graph topological dimension: 2\n");CHKERRQ(ierr);
150e9627c49SStefano Zampini     } else {
151efd4aadfSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Connectivity graph topological dimension: 3\n");CHKERRQ(ierr);
152e9627c49SStefano Zampini     }
153aefa1729SStefano Zampini     if (pcbddc->graphmaxcount != PETSC_MAX_INT) {
154efd4aadfSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Graph max count: %D\n",pcbddc->graphmaxcount);CHKERRQ(ierr);
155aefa1729SStefano Zampini     }
15650e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Use vertices: %d (vertex size %D)\n",pcbddc->use_vertices,pcbddc->vertex_size);CHKERRQ(ierr);
157efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use edges: %d\n",pcbddc->use_edges);CHKERRQ(ierr);
158efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use faces: %d\n",pcbddc->use_faces);CHKERRQ(ierr);
159efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use true near null space: %d\n",pcbddc->use_nnsp_true);CHKERRQ(ierr);
160efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use QR for single constraints on cc: %d\n",pcbddc->use_qr_single);CHKERRQ(ierr);
161efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use change of basis on local edge nodes: %d\n",pcbddc->use_change_of_basis);CHKERRQ(ierr);
162efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use change of basis on local face nodes: %d\n",pcbddc->use_change_on_faces);CHKERRQ(ierr);
163efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  User defined change of basis matrix: %d\n",!!pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
164efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Has change of basis matrix: %d\n",!!pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
165efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Eliminate dirichlet boundary dofs: %d\n",pcbddc->eliminate_dirdofs);CHKERRQ(ierr);
166efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Switch on static condensation ops around the interface preconditioner: %d\n",pcbddc->switch_static);CHKERRQ(ierr);
167efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use exact dirichlet trick: %d\n",pcbddc->use_exact_dirichlet_trick);CHKERRQ(ierr);
16850e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Multilevel max levels: %D\n",pcbddc->max_levels);CHKERRQ(ierr);
16950e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Multilevel coarsening ratio: %D\n",pcbddc->coarsening_ratio);CHKERRQ(ierr);
170efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use estimated eigs for coarse problem: %d\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
171efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use deluxe scaling: %d\n",pcbddc->use_deluxe_scaling);CHKERRQ(ierr);
172efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use deluxe zerorows: %d\n",pcbddc->deluxe_zerorows);CHKERRQ(ierr);
173efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use deluxe singlemat: %d\n",pcbddc->deluxe_singlemat);CHKERRQ(ierr);
174efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Rebuild interface graph for Schur principal minors: %d\n",pcbddc->sub_schurs_rebuild);CHKERRQ(ierr);
17550e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Number of dofs' layers for the computation of principal minors: %D\n",pcbddc->sub_schurs_layers);CHKERRQ(ierr);
176efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use user CSR graph to compute successive layers: %d\n",pcbddc->sub_schurs_use_useradj);CHKERRQ(ierr);
177bd2a564bSStefano Zampini     if (pcbddc->adaptive_threshold[1] != pcbddc->adaptive_threshold[0]) {
178bd2a564bSStefano 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);
179bd2a564bSStefano Zampini     } else {
180bd2a564bSStefano 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);
181bd2a564bSStefano Zampini     }
18250e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Min constraints / connected component: %D\n",pcbddc->adaptive_nmin);CHKERRQ(ierr);
18350e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Max constraints / connected component: %D\n",pcbddc->adaptive_nmax);CHKERRQ(ierr);
184efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Invert exact Schur complement for adaptive selection: %d\n",pcbddc->sub_schurs_exact_schur);CHKERRQ(ierr);
185efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Symmetric computation of primal basis functions: %d\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
18650e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Num. Procs. to map coarse adjacency list: %D\n",pcbddc->coarse_adj_red);CHKERRQ(ierr);
18750e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Coarse eqs per proc (significant at the coarsest level): %D\n",pcbddc->coarse_eqs_per_proc);CHKERRQ(ierr);
1888361f951SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Detect disconnected: %d (filter %d)\n",pcbddc->detect_disconnected,pcbddc->detect_disconnected_filter);CHKERRQ(ierr);
189efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Benign subspace trick: %d (change explicit %d)\n",pcbddc->benign_saddle_point,pcbddc->benign_change_explicit);CHKERRQ(ierr);
190efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Benign subspace trick is active: %d\n",pcbddc->benign_have_null);CHKERRQ(ierr);
19115579a77SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Algebraic computation of no-net-flux: %d\n",pcbddc->compute_nonetflux);CHKERRQ(ierr);
192b74ba07aSstefano_zampini     if (!pc->setupcalled) PetscFunctionReturn(0);
1936b78500eSPatrick Sanan 
194fbad9177SStefano Zampini     /* compute interface size */
195e9627c49SStefano Zampini     ierr = VecSet(pcis->vec1_B,1.0);CHKERRQ(ierr);
196e9627c49SStefano Zampini     ierr = MatCreateVecs(pc->pmat,&counter,0);CHKERRQ(ierr);
197e9627c49SStefano Zampini     ierr = VecSet(counter,0.0);CHKERRQ(ierr);
198e9627c49SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
199e9627c49SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
200e9627c49SStefano Zampini     ierr = VecSum(counter,&interface_size);CHKERRQ(ierr);
201e9627c49SStefano Zampini     ierr = VecDestroy(&counter);CHKERRQ(ierr);
202fbad9177SStefano Zampini 
203fbad9177SStefano Zampini     /* compute some statistics on the domain decomposition */
204e9627c49SStefano Zampini     gsum[0] = 1;
205fbad9177SStefano Zampini     gsum[1] = gsum[2] = gsum[3] = gsum[4] = gsum[5] = 0;
206e9627c49SStefano Zampini     loc[0]  = !!pcis->n;
207e9627c49SStefano Zampini     loc[1]  = pcis->n - pcis->n_B;
208e9627c49SStefano Zampini     loc[2]  = pcis->n_B;
209e9627c49SStefano Zampini     loc[3]  = pcbddc->local_primal_size;
210345ecf6cSStefano Zampini     loc[4]  = pcis->n;
211fbad9177SStefano Zampini     loc[5]  = pcbddc->n_local_subs > 0 ? pcbddc->n_local_subs : (pcis->n ? 1 : 0);
212fbad9177SStefano Zampini     loc[6]  = pcbddc->benign_n;
213fbad9177SStefano Zampini     ierr = MPI_Reduce(loc,gsum,6,MPIU_INT64,MPI_SUM,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
214fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = -1;
215fbad9177SStefano Zampini     ierr = MPI_Reduce(loc,gmax,6,MPIU_INT64,MPI_MAX,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
216fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = PETSC_MAX_INT;
217fbad9177SStefano Zampini     ierr = MPI_Reduce(loc,gmin,6,MPIU_INT64,MPI_MIN,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
218fbad9177SStefano Zampini     ierr = MPI_Reduce(&loc[6],&totbenign,1,MPIU_INT64,MPI_SUM,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
219e9627c49SStefano Zampini     if (pcbddc->coarse_size) {
220e9627c49SStefano Zampini       ratio1 = pc->pmat->rmap->N/(1.*pcbddc->coarse_size);
221e9627c49SStefano Zampini       ratio2 = PetscRealPart(interface_size)/pcbddc->coarse_size;
222e9627c49SStefano Zampini     }
223efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"********************************** STATISTICS AT LEVEL %d **********************************\n",pcbddc->current_level);CHKERRQ(ierr);
22450e0721cSStefano 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);
22550e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Coarsening ratios: all/coarse %D interface/coarse %D\n",(PetscInt)ratio1,(PetscInt)ratio2);CHKERRQ(ierr);
22650e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Active processes : %D\n",(PetscInt)gsum[0]);CHKERRQ(ierr);
22750e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Total subdomains : %D\n",(PetscInt)gsum[5]);CHKERRQ(ierr);
228345ecf6cSStefano Zampini     if (pcbddc->benign_have_null) {
22950e0721cSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"  Benign subs      : %D\n",(PetscInt)totbenign);CHKERRQ(ierr);
230345ecf6cSStefano Zampini     }
23150e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Dofs type        :\tMIN\tMAX\tMEAN\n");CHKERRQ(ierr);
23250e0721cSStefano 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);
23350e0721cSStefano 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);
23450e0721cSStefano 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);
23550e0721cSStefano 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);
23650e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Local     subs   :\t%D\t%D\n"    ,(PetscInt)gmin[5],(PetscInt)gmax[5]);CHKERRQ(ierr);
23715579a77SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
23815579a77SStefano Zampini 
23915579a77SStefano Zampini     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
24015579a77SStefano Zampini 
24115579a77SStefano Zampini     /* local solvers */
24215579a77SStefano Zampini     ierr = PetscViewerGetSubViewer(viewer,PetscObjectComm((PetscObject)pcbddc->ksp_D),&subviewer);CHKERRQ(ierr);
24315579a77SStefano Zampini     if (!rank) {
24415579a77SStefano Zampini       ierr = PetscViewerASCIIPrintf(subviewer,"--- Interior solver (rank 0)\n");CHKERRQ(ierr);
24515579a77SStefano Zampini       ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr);
24615579a77SStefano Zampini       ierr = KSPView(pcbddc->ksp_D,subviewer);CHKERRQ(ierr);
24715579a77SStefano Zampini       ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr);
24815579a77SStefano Zampini       ierr = PetscViewerASCIIPrintf(subviewer,"--- Correction solver (rank 0)\n");CHKERRQ(ierr);
24915579a77SStefano Zampini       ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr);
25015579a77SStefano Zampini       ierr = KSPView(pcbddc->ksp_R,subviewer);CHKERRQ(ierr);
25115579a77SStefano Zampini       ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr);
25215579a77SStefano Zampini       ierr = PetscViewerFlush(subviewer);CHKERRQ(ierr);
25315579a77SStefano Zampini     }
25415579a77SStefano Zampini     ierr = PetscViewerRestoreSubViewer(viewer,PetscObjectComm((PetscObject)pcbddc->ksp_D),&subviewer);CHKERRQ(ierr);
25527b6a85dSStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
256e9627c49SStefano Zampini 
257fbad9177SStefano Zampini     /* the coarse problem can be handled by a different communicator */
258e9627c49SStefano Zampini     if (pcbddc->coarse_ksp) color = 1;
259e9627c49SStefano Zampini     else color = 0;
2604b2aedd3SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
261e9627c49SStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)pc),&subcomm);CHKERRQ(ierr);
2624b2aedd3SStefano Zampini     ierr = PetscSubcommSetNumber(subcomm,PetscMin(size,2));CHKERRQ(ierr);
263e9627c49SStefano Zampini     ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
264e9627c49SStefano Zampini     ierr = PetscViewerGetSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer);CHKERRQ(ierr);
265e9627c49SStefano Zampini     if (color == 1) {
26615579a77SStefano Zampini       ierr = PetscViewerASCIIPrintf(subviewer,"--- Coarse solver\n");CHKERRQ(ierr);
26715579a77SStefano Zampini       ierr = PetscViewerASCIIPushTab(subviewer);CHKERRQ(ierr);
268e9627c49SStefano Zampini       ierr = KSPView(pcbddc->coarse_ksp,subviewer);CHKERRQ(ierr);
26915579a77SStefano Zampini       ierr = PetscViewerASCIIPopTab(subviewer);CHKERRQ(ierr);
270e9627c49SStefano Zampini       ierr = PetscViewerFlush(subviewer);CHKERRQ(ierr);
271e9627c49SStefano Zampini     }
272e9627c49SStefano Zampini     ierr = PetscViewerRestoreSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer);CHKERRQ(ierr);
273e9627c49SStefano Zampini     ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
274e9627c49SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
275e9627c49SStefano Zampini   }
2766b78500eSPatrick Sanan   PetscFunctionReturn(0);
2776b78500eSPatrick Sanan }
278a13144ffSStefano Zampini 
2791e0482f5SStefano Zampini static PetscErrorCode PCBDDCSetDiscreteGradient_BDDC(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
280a13144ffSStefano Zampini {
281a13144ffSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
282a13144ffSStefano Zampini   PetscErrorCode ierr;
283a13144ffSStefano Zampini 
284a13144ffSStefano Zampini   PetscFunctionBegin;
285a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)G);CHKERRQ(ierr);
286a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
287a13144ffSStefano Zampini   pcbddc->discretegradient = G;
288a13144ffSStefano Zampini   pcbddc->nedorder         = order > 0 ? order : -order;
289495a2a07SStefano Zampini   pcbddc->nedfield         = field;
2901e0482f5SStefano Zampini   pcbddc->nedglobal        = global;
2911e0482f5SStefano Zampini   pcbddc->conforming       = conforming;
292a13144ffSStefano Zampini   PetscFunctionReturn(0);
293a13144ffSStefano Zampini }
294a13144ffSStefano Zampini 
295a13144ffSStefano Zampini /*@
296a13144ffSStefano Zampini  PCBDDCSetDiscreteGradient - Sets the discrete gradient
297a13144ffSStefano Zampini 
298a13144ffSStefano Zampini    Collective on PC
299a13144ffSStefano Zampini 
300a13144ffSStefano Zampini    Input Parameters:
301a13144ffSStefano Zampini +  pc         - the preconditioning context
302a13144ffSStefano Zampini .  G          - the discrete gradient matrix (should be in AIJ format)
303a13144ffSStefano Zampini .  order      - the order of the Nedelec space (1 for the lowest order)
304495a2a07SStefano Zampini .  field      - the field id of the Nedelec dofs (not used if the fields have not been specified)
3051e0482f5SStefano Zampini .  global     - the type of global ordering for the rows of G
306a13144ffSStefano Zampini -  conforming - whether the mesh is conforming or not
307a13144ffSStefano Zampini 
308a13144ffSStefano Zampini    Level: advanced
309a13144ffSStefano Zampini 
31095452b02SPatrick Sanan    Notes:
31195452b02SPatrick Sanan     The discrete gradient matrix G is used to analyze the subdomain edges, and it should not contain any zero entry.
312495a2a07SStefano Zampini           For variable order spaces, the order should be set to zero.
3131e0482f5SStefano Zampini           If global is true, the rows of G should be given in global ordering for the whole dofs;
3141e0482f5SStefano Zampini           if false, the ordering should be global for the Nedelec field.
3151e0482f5SStefano 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
3161e0482f5SStefano Zampini           and geid the one for the Nedelec field.
317a13144ffSStefano Zampini 
318495a2a07SStefano Zampini .seealso: PCBDDC,PCBDDCSetDofsSplitting(),PCBDDCSetDofsSplittingLocal()
319a13144ffSStefano Zampini @*/
3201e0482f5SStefano Zampini PetscErrorCode PCBDDCSetDiscreteGradient(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
321a13144ffSStefano Zampini {
322a13144ffSStefano Zampini   PetscErrorCode ierr;
323a13144ffSStefano Zampini 
324a13144ffSStefano Zampini   PetscFunctionBegin;
325a13144ffSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
326a13144ffSStefano Zampini   PetscValidHeaderSpecific(G,MAT_CLASSID,2);
327a13144ffSStefano Zampini   PetscValidLogicalCollectiveInt(pc,order,3);
3281e0482f5SStefano Zampini   PetscValidLogicalCollectiveInt(pc,field,4);
3291e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc,global,5);
3301e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc,conforming,6);
3311e0482f5SStefano Zampini   PetscCheckSameComm(pc,1,G,2);
3321e0482f5SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDiscreteGradient_C",(PC,Mat,PetscInt,PetscInt,PetscBool,PetscBool),(pc,G,order,field,global,conforming));CHKERRQ(ierr);
333a13144ffSStefano Zampini   PetscFunctionReturn(0);
334a13144ffSStefano Zampini }
335a13144ffSStefano Zampini 
3368ae0ca82SStefano Zampini static PetscErrorCode PCBDDCSetDivergenceMat_BDDC(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
337a198735bSStefano Zampini {
338a198735bSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
339a198735bSStefano Zampini   PetscErrorCode ierr;
3406b78500eSPatrick Sanan 
341a198735bSStefano Zampini   PetscFunctionBegin;
342a198735bSStefano Zampini   ierr = PetscObjectReference((PetscObject)divudotp);CHKERRQ(ierr);
343a198735bSStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
344a198735bSStefano Zampini   pcbddc->divudotp = divudotp;
3458ae0ca82SStefano Zampini   pcbddc->divudotp_trans = trans;
346a198735bSStefano Zampini   pcbddc->compute_nonetflux = PETSC_TRUE;
347a198735bSStefano Zampini   if (vl2l) {
348a198735bSStefano Zampini     ierr = PetscObjectReference((PetscObject)vl2l);CHKERRQ(ierr);
349fa23a32eSStefano Zampini     ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
350a198735bSStefano Zampini     pcbddc->divudotp_vl2l = vl2l;
351a198735bSStefano Zampini   }
352a198735bSStefano Zampini   PetscFunctionReturn(0);
353a198735bSStefano Zampini }
3543d996552SStefano Zampini 
355a198735bSStefano Zampini /*@
356a198735bSStefano Zampini  PCBDDCSetDivergenceMat - Sets the linear operator representing \int_\Omega \div {\bf u} \cdot p dx
357a198735bSStefano Zampini 
358a198735bSStefano Zampini    Collective on PC
359a198735bSStefano Zampini 
360a198735bSStefano Zampini    Input Parameters:
361a198735bSStefano Zampini +  pc - the preconditioning context
362a198735bSStefano Zampini .  divudotp - the matrix (must be of type MATIS)
3638ae0ca82SStefano Zampini .  trans - if trans if false (resp. true), then pressures are in the test (trial) space and velocities are in the trial (test) space.
36405a3bf82SStefano 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
365a198735bSStefano Zampini 
366a198735bSStefano Zampini    Level: advanced
367a198735bSStefano Zampini 
36895452b02SPatrick Sanan    Notes:
36995452b02SPatrick Sanan     This auxiliary matrix is used to compute quadrature weights representing the net-flux across subdomain boundaries
37005a3bf82SStefano Zampini           If vl2l is NULL, the local ordering for velocities in divudotp should match that of the preconditioning matrix
371a198735bSStefano Zampini 
372a198735bSStefano Zampini .seealso: PCBDDC
373a198735bSStefano Zampini @*/
3748ae0ca82SStefano Zampini PetscErrorCode PCBDDCSetDivergenceMat(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
375a198735bSStefano Zampini {
376a198735bSStefano Zampini   PetscBool      ismatis;
377a198735bSStefano Zampini   PetscErrorCode ierr;
378a198735bSStefano Zampini 
379a198735bSStefano Zampini   PetscFunctionBegin;
380a198735bSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
381a198735bSStefano Zampini   PetscValidHeaderSpecific(divudotp,MAT_CLASSID,2);
382a198735bSStefano Zampini   PetscCheckSameComm(pc,1,divudotp,2);
3838ae0ca82SStefano Zampini   PetscValidLogicalCollectiveBool(pc,trans,3);
3841b24a7afSStefano Zampini   if (vl2l) PetscValidHeaderSpecific(vl2l,IS_CLASSID,4);
385a198735bSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)divudotp,MATIS,&ismatis);CHKERRQ(ierr);
386a198735bSStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Divergence matrix needs to be of type MATIS");
3878ae0ca82SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDivergenceMat_C",(PC,Mat,PetscBool,IS),(pc,divudotp,trans,vl2l));CHKERRQ(ierr);
388a198735bSStefano Zampini   PetscFunctionReturn(0);
389a198735bSStefano Zampini }
3902d505d7fSStefano Zampini 
3911dd7afcfSStefano Zampini static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change, PetscBool interior)
392b9b85e73SStefano Zampini {
393b9b85e73SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
394b9b85e73SStefano Zampini   PetscErrorCode ierr;
395b9b85e73SStefano Zampini 
396b9b85e73SStefano Zampini   PetscFunctionBegin;
397b9b85e73SStefano Zampini   ierr = PetscObjectReference((PetscObject)change);CHKERRQ(ierr);
39856282151SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
399b9b85e73SStefano Zampini   pcbddc->user_ChangeOfBasisMatrix = change;
4001dd7afcfSStefano Zampini   pcbddc->change_interior = interior;
401b9b85e73SStefano Zampini   PetscFunctionReturn(0);
402b9b85e73SStefano Zampini }
403b9b85e73SStefano Zampini /*@
404906d46d4SStefano Zampini  PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs
405b9b85e73SStefano Zampini 
406b9b85e73SStefano Zampini    Collective on PC
407b9b85e73SStefano Zampini 
408b9b85e73SStefano Zampini    Input Parameters:
409b9b85e73SStefano Zampini +  pc - the preconditioning context
4101dd7afcfSStefano Zampini .  change - the change of basis matrix
4111dd7afcfSStefano Zampini -  interior - whether or not the change of basis modifies interior dofs
412b9b85e73SStefano Zampini 
413b9b85e73SStefano Zampini    Level: intermediate
414b9b85e73SStefano Zampini 
415b9b85e73SStefano Zampini    Notes:
416b9b85e73SStefano Zampini 
417b9b85e73SStefano Zampini .seealso: PCBDDC
418b9b85e73SStefano Zampini @*/
4191dd7afcfSStefano Zampini PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change, PetscBool interior)
420b9b85e73SStefano Zampini {
421b9b85e73SStefano Zampini   PetscErrorCode ierr;
422b9b85e73SStefano Zampini 
423b9b85e73SStefano Zampini   PetscFunctionBegin;
424b9b85e73SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
425b9b85e73SStefano Zampini   PetscValidHeaderSpecific(change,MAT_CLASSID,2);
426906d46d4SStefano Zampini   PetscCheckSameComm(pc,1,change,2);
427906d46d4SStefano Zampini   if (pc->mat) {
428906d46d4SStefano Zampini     PetscInt rows_c,cols_c,rows,cols;
429906d46d4SStefano Zampini     ierr = MatGetSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
430906d46d4SStefano Zampini     ierr = MatGetSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
431e0fe2d75SToby 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);
432e0fe2d75SToby 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);
433906d46d4SStefano Zampini     ierr = MatGetLocalSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
434906d46d4SStefano Zampini     ierr = MatGetLocalSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
435e0fe2d75SToby 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);
436e0fe2d75SToby 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);
437906d46d4SStefano Zampini   }
4381dd7afcfSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetChangeOfBasisMat_C",(PC,Mat,PetscBool),(pc,change,interior));CHKERRQ(ierr);
439b9b85e73SStefano Zampini   PetscFunctionReturn(0);
440b9b85e73SStefano Zampini }
4412d505d7fSStefano Zampini 
44230368db7SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesIS_BDDC(PC pc, IS PrimalVertices)
44330368db7SStefano Zampini {
44430368db7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
44556282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
44630368db7SStefano Zampini   PetscErrorCode ierr;
44730368db7SStefano Zampini 
44830368db7SStefano Zampini   PetscFunctionBegin;
44956282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
45056282151SStefano Zampini   if (pcbddc->user_primal_vertices) {
45156282151SStefano Zampini     ierr = ISEqual(PrimalVertices,pcbddc->user_primal_vertices,&isequal);CHKERRQ(ierr);
45256282151SStefano Zampini   }
45330368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
45430368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
45530368db7SStefano Zampini   pcbddc->user_primal_vertices = PrimalVertices;
45656282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
45730368db7SStefano Zampini   PetscFunctionReturn(0);
45830368db7SStefano Zampini }
459ab8c8b98SStefano Zampini 
46030368db7SStefano Zampini /*@
46130368db7SStefano Zampini  PCBDDCSetPrimalVerticesIS - Set additional user defined primal vertices in PCBDDC
46230368db7SStefano Zampini 
46330368db7SStefano Zampini    Collective
46430368db7SStefano Zampini 
46530368db7SStefano Zampini    Input Parameters:
46630368db7SStefano Zampini +  pc - the preconditioning context
46730368db7SStefano Zampini -  PrimalVertices - index set of primal vertices in global numbering (can be empty)
46830368db7SStefano Zampini 
46930368db7SStefano Zampini    Level: intermediate
47030368db7SStefano Zampini 
47130368db7SStefano Zampini    Notes:
47230368db7SStefano Zampini      Any process can list any global node
47330368db7SStefano Zampini 
4743100ebe3SStefano Zampini .seealso: PCBDDC, PCBDDCGetPrimalVerticesIS(), PCBDDCSetPrimalVerticesLocalIS(), PCBDDCGetPrimalVerticesLocalIS()
47530368db7SStefano Zampini @*/
47630368db7SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesIS(PC pc, IS PrimalVertices)
47730368db7SStefano Zampini {
47830368db7SStefano Zampini   PetscErrorCode ierr;
47930368db7SStefano Zampini 
48030368db7SStefano Zampini   PetscFunctionBegin;
48130368db7SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
48230368db7SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
48330368db7SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
48430368db7SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
48530368db7SStefano Zampini   PetscFunctionReturn(0);
48630368db7SStefano Zampini }
4872d505d7fSStefano Zampini 
4883100ebe3SStefano Zampini static PetscErrorCode PCBDDCGetPrimalVerticesIS_BDDC(PC pc, IS *is)
4893100ebe3SStefano Zampini {
4903100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC*)pc->data;
4913100ebe3SStefano Zampini 
4923100ebe3SStefano Zampini   PetscFunctionBegin;
4933100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices;
4943100ebe3SStefano Zampini   PetscFunctionReturn(0);
4953100ebe3SStefano Zampini }
4963100ebe3SStefano Zampini 
4973100ebe3SStefano Zampini /*@
4983100ebe3SStefano Zampini  PCBDDCGetPrimalVerticesIS - Get user defined primal vertices set with PCBDDCSetPrimalVerticesIS()
4993100ebe3SStefano Zampini 
5003100ebe3SStefano Zampini    Collective
5013100ebe3SStefano Zampini 
5023100ebe3SStefano Zampini    Input Parameters:
5033100ebe3SStefano Zampini .  pc - the preconditioning context
5043100ebe3SStefano Zampini 
5053100ebe3SStefano Zampini    Output Parameters:
5063100ebe3SStefano Zampini .  is - index set of primal vertices in global numbering (NULL if not set)
5073100ebe3SStefano Zampini 
5083100ebe3SStefano Zampini    Level: intermediate
5093100ebe3SStefano Zampini 
5103100ebe3SStefano Zampini    Notes:
5113100ebe3SStefano Zampini 
5123100ebe3SStefano Zampini .seealso: PCBDDC, PCBDDCSetPrimalVerticesIS(), PCBDDCSetPrimalVerticesLocalIS(), PCBDDCGetPrimalVerticesLocalIS()
5133100ebe3SStefano Zampini @*/
5143100ebe3SStefano Zampini PetscErrorCode PCBDDCGetPrimalVerticesIS(PC pc, IS *is)
5153100ebe3SStefano Zampini {
5163100ebe3SStefano Zampini   PetscErrorCode ierr;
5173100ebe3SStefano Zampini 
5183100ebe3SStefano Zampini   PetscFunctionBegin;
5193100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5203100ebe3SStefano Zampini   PetscValidPointer(is,2);
5213100ebe3SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetPrimalVerticesIS_C",(PC,IS*),(pc,is));CHKERRQ(ierr);
5223100ebe3SStefano Zampini   PetscFunctionReturn(0);
5233100ebe3SStefano Zampini }
5243100ebe3SStefano Zampini 
525674ae819SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
526674ae819SStefano Zampini {
527674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
52856282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
529674ae819SStefano Zampini   PetscErrorCode ierr;
5301e6b0712SBarry Smith 
531674ae819SStefano Zampini   PetscFunctionBegin;
53256282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
53356282151SStefano Zampini   if (pcbddc->user_primal_vertices_local) {
53456282151SStefano Zampini     ierr = ISEqual(PrimalVertices,pcbddc->user_primal_vertices_local,&isequal);CHKERRQ(ierr);
53556282151SStefano Zampini   }
536674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
53730368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
53830368db7SStefano Zampini   pcbddc->user_primal_vertices_local = PrimalVertices;
53956282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
540674ae819SStefano Zampini   PetscFunctionReturn(0);
541674ae819SStefano Zampini }
5423100ebe3SStefano Zampini 
543674ae819SStefano Zampini /*@
54428509bceSStefano Zampini  PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in PCBDDC
545674ae819SStefano Zampini 
54617eb1463SStefano Zampini    Collective
547674ae819SStefano Zampini 
548674ae819SStefano Zampini    Input Parameters:
549674ae819SStefano Zampini +  pc - the preconditioning context
55017eb1463SStefano Zampini -  PrimalVertices - index set of primal vertices in local numbering (can be empty)
551674ae819SStefano Zampini 
552674ae819SStefano Zampini    Level: intermediate
553674ae819SStefano Zampini 
554674ae819SStefano Zampini    Notes:
555674ae819SStefano Zampini 
5563100ebe3SStefano Zampini .seealso: PCBDDC, PCBDDCSetPrimalVerticesIS(), PCBDDCGetPrimalVerticesIS(), PCBDDCGetPrimalVerticesLocalIS()
557674ae819SStefano Zampini @*/
558674ae819SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
559674ae819SStefano Zampini {
560674ae819SStefano Zampini   PetscErrorCode ierr;
561674ae819SStefano Zampini 
562674ae819SStefano Zampini   PetscFunctionBegin;
563674ae819SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
564674ae819SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
56517eb1463SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
566674ae819SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
567674ae819SStefano Zampini   PetscFunctionReturn(0);
568674ae819SStefano Zampini }
5692d505d7fSStefano Zampini 
5703100ebe3SStefano Zampini static PetscErrorCode PCBDDCGetPrimalVerticesLocalIS_BDDC(PC pc, IS *is)
5713100ebe3SStefano Zampini {
5723100ebe3SStefano Zampini   PC_BDDC *pcbddc = (PC_BDDC*)pc->data;
5733100ebe3SStefano Zampini 
5743100ebe3SStefano Zampini   PetscFunctionBegin;
5753100ebe3SStefano Zampini   *is = pcbddc->user_primal_vertices_local;
5763100ebe3SStefano Zampini   PetscFunctionReturn(0);
5773100ebe3SStefano Zampini }
5783100ebe3SStefano Zampini 
5793100ebe3SStefano Zampini /*@
5803100ebe3SStefano Zampini  PCBDDCGetPrimalVerticesLocalIS - Get user defined primal vertices set with PCBDDCSetPrimalVerticesLocalIS()
5813100ebe3SStefano Zampini 
5823100ebe3SStefano Zampini    Collective
5833100ebe3SStefano Zampini 
5843100ebe3SStefano Zampini    Input Parameters:
5853100ebe3SStefano Zampini .  pc - the preconditioning context
5863100ebe3SStefano Zampini 
5873100ebe3SStefano Zampini    Output Parameters:
5883100ebe3SStefano Zampini .  is - index set of primal vertices in local numbering (NULL if not set)
5893100ebe3SStefano Zampini 
5903100ebe3SStefano Zampini    Level: intermediate
5913100ebe3SStefano Zampini 
5923100ebe3SStefano Zampini    Notes:
5933100ebe3SStefano Zampini 
5943100ebe3SStefano Zampini .seealso: PCBDDC, PCBDDCSetPrimalVerticesIS(), PCBDDCGetPrimalVerticesIS(), PCBDDCSetPrimalVerticesLocalIS()
5953100ebe3SStefano Zampini @*/
5963100ebe3SStefano Zampini PetscErrorCode PCBDDCGetPrimalVerticesLocalIS(PC pc, IS *is)
5973100ebe3SStefano Zampini {
5983100ebe3SStefano Zampini   PetscErrorCode ierr;
5993100ebe3SStefano Zampini 
6003100ebe3SStefano Zampini   PetscFunctionBegin;
6013100ebe3SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
6023100ebe3SStefano Zampini   PetscValidPointer(is,2);
6033100ebe3SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetPrimalVerticesLocalIS_C",(PC,IS*),(pc,is));CHKERRQ(ierr);
6043100ebe3SStefano Zampini   PetscFunctionReturn(0);
6053100ebe3SStefano Zampini }
6063100ebe3SStefano Zampini 
6074fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k)
6084fad6a16SStefano Zampini {
6094fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
6104fad6a16SStefano Zampini 
6114fad6a16SStefano Zampini   PetscFunctionBegin;
6124fad6a16SStefano Zampini   pcbddc->coarsening_ratio = k;
6134fad6a16SStefano Zampini   PetscFunctionReturn(0);
6144fad6a16SStefano Zampini }
6151e6b0712SBarry Smith 
6164fad6a16SStefano Zampini /*@
61728509bceSStefano Zampini  PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel
6184fad6a16SStefano Zampini 
6194fad6a16SStefano Zampini    Logically collective on PC
6204fad6a16SStefano Zampini 
6214fad6a16SStefano Zampini    Input Parameters:
6224fad6a16SStefano Zampini +  pc - the preconditioning context
62328509bceSStefano Zampini -  k - coarsening ratio (H/h at the coarser level)
6244fad6a16SStefano Zampini 
6250f202f7eSStefano Zampini    Options Database Keys:
6260f202f7eSStefano Zampini .    -pc_bddc_coarsening_ratio
6274fad6a16SStefano Zampini 
6284fad6a16SStefano Zampini    Level: intermediate
6294fad6a16SStefano Zampini 
6304fad6a16SStefano Zampini    Notes:
6310f202f7eSStefano Zampini      Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level
6324fad6a16SStefano Zampini 
6330f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetLevels()
6344fad6a16SStefano Zampini @*/
6354fad6a16SStefano Zampini PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k)
6364fad6a16SStefano Zampini {
6374fad6a16SStefano Zampini   PetscErrorCode ierr;
6384fad6a16SStefano Zampini 
6394fad6a16SStefano Zampini   PetscFunctionBegin;
6404fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
6412b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,k,2);
6424fad6a16SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));CHKERRQ(ierr);
6434fad6a16SStefano Zampini   PetscFunctionReturn(0);
6444fad6a16SStefano Zampini }
6452b510759SStefano Zampini 
646b8ffe317SStefano Zampini /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */
647b8ffe317SStefano Zampini static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc,PetscBool flg)
648b8ffe317SStefano Zampini {
649b8ffe317SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
650b8ffe317SStefano Zampini 
651b8ffe317SStefano Zampini   PetscFunctionBegin;
65285c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = flg;
653b8ffe317SStefano Zampini   PetscFunctionReturn(0);
654b8ffe317SStefano Zampini }
655b8ffe317SStefano Zampini 
656b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool flg)
6572b510759SStefano Zampini {
6582b510759SStefano Zampini   PetscErrorCode ierr;
6592b510759SStefano Zampini 
6602b510759SStefano Zampini   PetscFunctionBegin;
6612b510759SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
662b8ffe317SStefano Zampini   PetscValidLogicalCollectiveBool(pc,flg,2);
663b8ffe317SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetUseExactDirichlet_C",(PC,PetscBool),(pc,flg));CHKERRQ(ierr);
6642b510759SStefano Zampini   PetscFunctionReturn(0);
6652b510759SStefano Zampini }
6661e6b0712SBarry Smith 
6672b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc,PetscInt level)
6684fad6a16SStefano Zampini {
6694fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
6704fad6a16SStefano Zampini 
6714fad6a16SStefano Zampini   PetscFunctionBegin;
6722b510759SStefano Zampini   pcbddc->current_level = level;
6734fad6a16SStefano Zampini   PetscFunctionReturn(0);
6744fad6a16SStefano Zampini }
6751e6b0712SBarry Smith 
676b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level)
677b8ffe317SStefano Zampini {
678b8ffe317SStefano Zampini   PetscErrorCode ierr;
679b8ffe317SStefano Zampini 
680b8ffe317SStefano Zampini   PetscFunctionBegin;
681b8ffe317SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
682b8ffe317SStefano Zampini   PetscValidLogicalCollectiveInt(pc,level,2);
683b8ffe317SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLevel_C",(PC,PetscInt),(pc,level));CHKERRQ(ierr);
684b8ffe317SStefano Zampini   PetscFunctionReturn(0);
685b8ffe317SStefano Zampini }
686b8ffe317SStefano Zampini 
6872b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc,PetscInt levels)
6882b510759SStefano Zampini {
6892b510759SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
6902b510759SStefano Zampini 
6912b510759SStefano Zampini   PetscFunctionBegin;
6926080607fSStefano 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);
6932b510759SStefano Zampini   pcbddc->max_levels = levels;
6942b510759SStefano Zampini   PetscFunctionReturn(0);
6952b510759SStefano Zampini }
6962b510759SStefano Zampini 
6974fad6a16SStefano Zampini /*@
69837ebbdf7SStefano Zampini  PCBDDCSetLevels - Sets the maximum number of additional levels allowed for multilevel BDDC
6994fad6a16SStefano Zampini 
7004fad6a16SStefano Zampini    Logically collective on PC
7014fad6a16SStefano Zampini 
7024fad6a16SStefano Zampini    Input Parameters:
7034fad6a16SStefano Zampini +  pc - the preconditioning context
70437ebbdf7SStefano Zampini -  levels - the maximum number of levels
7054fad6a16SStefano Zampini 
7060f202f7eSStefano Zampini    Options Database Keys:
7070f202f7eSStefano Zampini .    -pc_bddc_levels
7084fad6a16SStefano Zampini 
7094fad6a16SStefano Zampini    Level: intermediate
7104fad6a16SStefano Zampini 
7114fad6a16SStefano Zampini    Notes:
71237ebbdf7SStefano Zampini      The default value is 0, that gives the classical two-levels BDDC
7134fad6a16SStefano Zampini 
7140f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetCoarseningRatio()
7154fad6a16SStefano Zampini @*/
7162b510759SStefano Zampini PetscErrorCode PCBDDCSetLevels(PC pc,PetscInt levels)
7174fad6a16SStefano Zampini {
7184fad6a16SStefano Zampini   PetscErrorCode ierr;
7194fad6a16SStefano Zampini 
7204fad6a16SStefano Zampini   PetscFunctionBegin;
7214fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
7222b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,levels,2);
7232b510759SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLevels_C",(PC,PetscInt),(pc,levels));CHKERRQ(ierr);
7244fad6a16SStefano Zampini   PetscFunctionReturn(0);
7254fad6a16SStefano Zampini }
7261e6b0712SBarry Smith 
7273b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
7283b03a366Sstefano_zampini {
7293b03a366Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
73056282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
7313b03a366Sstefano_zampini   PetscErrorCode ierr;
7323b03a366Sstefano_zampini 
7333b03a366Sstefano_zampini   PetscFunctionBegin;
73456282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
73556282151SStefano Zampini   if (pcbddc->DirichletBoundaries) {
73656282151SStefano Zampini     ierr = ISEqual(DirichletBoundaries,pcbddc->DirichletBoundaries,&isequal);CHKERRQ(ierr);
73756282151SStefano Zampini   }
738785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
739785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
7403b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
74136e030ebSStefano Zampini   pcbddc->DirichletBoundaries = DirichletBoundaries;
74256282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7433b03a366Sstefano_zampini   PetscFunctionReturn(0);
7443b03a366Sstefano_zampini }
7451e6b0712SBarry Smith 
7463b03a366Sstefano_zampini /*@
74728509bceSStefano Zampini  PCBDDCSetDirichletBoundaries - Set IS defining Dirichlet boundaries for the global problem.
7483b03a366Sstefano_zampini 
749785d1243SStefano Zampini    Collective
7503b03a366Sstefano_zampini 
7513b03a366Sstefano_zampini    Input Parameters:
7523b03a366Sstefano_zampini +  pc - the preconditioning context
753785d1243SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries
7543b03a366Sstefano_zampini 
7553b03a366Sstefano_zampini    Level: intermediate
7563b03a366Sstefano_zampini 
7570f202f7eSStefano Zampini    Notes:
7580f202f7eSStefano Zampini      Provide the information if you used MatZeroRows/Columns routines. Any process can list any global node
7593b03a366Sstefano_zampini 
7600f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetDirichletBoundariesLocal(), MatZeroRows(), MatZeroRowsColumns()
7613b03a366Sstefano_zampini @*/
7623b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
7633b03a366Sstefano_zampini {
7643b03a366Sstefano_zampini   PetscErrorCode ierr;
7653b03a366Sstefano_zampini 
7663b03a366Sstefano_zampini   PetscFunctionBegin;
7673b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
768674ae819SStefano Zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
769785d1243SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
7703b03a366Sstefano_zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
7713b03a366Sstefano_zampini   PetscFunctionReturn(0);
7723b03a366Sstefano_zampini }
7731e6b0712SBarry Smith 
77482ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc,IS DirichletBoundaries)
7753b03a366Sstefano_zampini {
7763b03a366Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
77756282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
7783b03a366Sstefano_zampini   PetscErrorCode ierr;
7793b03a366Sstefano_zampini 
7803b03a366Sstefano_zampini   PetscFunctionBegin;
78156282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
78256282151SStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
78356282151SStefano Zampini     ierr = ISEqual(DirichletBoundaries,pcbddc->DirichletBoundariesLocal,&isequal);CHKERRQ(ierr);
78456282151SStefano Zampini   }
785785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
786785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
7873b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
788785d1243SStefano Zampini   pcbddc->DirichletBoundariesLocal = DirichletBoundaries;
78956282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7903b03a366Sstefano_zampini   PetscFunctionReturn(0);
7913b03a366Sstefano_zampini }
7923b03a366Sstefano_zampini 
7933b03a366Sstefano_zampini /*@
79482ba6b80SStefano Zampini  PCBDDCSetDirichletBoundariesLocal - Set IS defining Dirichlet boundaries for the global problem in local ordering.
7953b03a366Sstefano_zampini 
796785d1243SStefano Zampini    Collective
7973b03a366Sstefano_zampini 
7983b03a366Sstefano_zampini    Input Parameters:
7993b03a366Sstefano_zampini +  pc - the preconditioning context
80082ba6b80SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries (in local ordering)
8013b03a366Sstefano_zampini 
8023b03a366Sstefano_zampini    Level: intermediate
8033b03a366Sstefano_zampini 
8043b03a366Sstefano_zampini    Notes:
8053b03a366Sstefano_zampini 
8060f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetDirichletBoundaries(), MatZeroRows(), MatZeroRowsColumns()
8073b03a366Sstefano_zampini @*/
80882ba6b80SStefano Zampini PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc,IS DirichletBoundaries)
8093b03a366Sstefano_zampini {
8103b03a366Sstefano_zampini   PetscErrorCode ierr;
8113b03a366Sstefano_zampini 
8123b03a366Sstefano_zampini   PetscFunctionBegin;
8133b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
8143b03a366Sstefano_zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
81582ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
81682ba6b80SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundariesLocal_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
8173b03a366Sstefano_zampini   PetscFunctionReturn(0);
8183b03a366Sstefano_zampini }
8193b03a366Sstefano_zampini 
82053cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
8210c7d97c5SJed Brown {
8220c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
82356282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
82453cdbc3dSStefano Zampini   PetscErrorCode ierr;
8250c7d97c5SJed Brown 
8260c7d97c5SJed Brown   PetscFunctionBegin;
82756282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
82856282151SStefano Zampini   if (pcbddc->NeumannBoundaries) {
82956282151SStefano Zampini     ierr = ISEqual(NeumannBoundaries,pcbddc->NeumannBoundaries,&isequal);CHKERRQ(ierr);
83056282151SStefano Zampini   }
831785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
832785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
83353cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
83436e030ebSStefano Zampini   pcbddc->NeumannBoundaries = NeumannBoundaries;
83556282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
8360c7d97c5SJed Brown   PetscFunctionReturn(0);
8370c7d97c5SJed Brown }
8381e6b0712SBarry Smith 
83957527edcSJed Brown /*@
84028509bceSStefano Zampini  PCBDDCSetNeumannBoundaries - Set IS defining Neumann boundaries for the global problem.
84157527edcSJed Brown 
842785d1243SStefano Zampini    Collective
84357527edcSJed Brown 
84457527edcSJed Brown    Input Parameters:
84557527edcSJed Brown +  pc - the preconditioning context
846785d1243SStefano Zampini -  NeumannBoundaries - parallel IS defining the Neumann boundaries
84757527edcSJed Brown 
84857527edcSJed Brown    Level: intermediate
84957527edcSJed Brown 
8500f202f7eSStefano Zampini    Notes:
8510f202f7eSStefano Zampini      Any process can list any global node
85257527edcSJed Brown 
8530f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetNeumannBoundariesLocal()
85457527edcSJed Brown @*/
85553cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
8560c7d97c5SJed Brown {
8570c7d97c5SJed Brown   PetscErrorCode ierr;
8580c7d97c5SJed Brown 
8590c7d97c5SJed Brown   PetscFunctionBegin;
8600c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
861674ae819SStefano Zampini   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
862785d1243SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
86353cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
86453cdbc3dSStefano Zampini   PetscFunctionReturn(0);
86553cdbc3dSStefano Zampini }
8661e6b0712SBarry Smith 
86782ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc,IS NeumannBoundaries)
8680c7d97c5SJed Brown {
8690c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
87056282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
8710c7d97c5SJed Brown   PetscErrorCode ierr;
8720c7d97c5SJed Brown 
8730c7d97c5SJed Brown   PetscFunctionBegin;
87456282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
87556282151SStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
87656282151SStefano Zampini     ierr = ISEqual(NeumannBoundaries,pcbddc->NeumannBoundariesLocal,&isequal);CHKERRQ(ierr);
87756282151SStefano Zampini   }
878785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
879785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
8800c7d97c5SJed Brown   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
881785d1243SStefano Zampini   pcbddc->NeumannBoundariesLocal = NeumannBoundaries;
88256282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
8830c7d97c5SJed Brown   PetscFunctionReturn(0);
8840c7d97c5SJed Brown }
8850c7d97c5SJed Brown 
8860c7d97c5SJed Brown /*@
88782ba6b80SStefano Zampini  PCBDDCSetNeumannBoundariesLocal - Set IS defining Neumann boundaries for the global problem in local ordering.
8880c7d97c5SJed Brown 
889785d1243SStefano Zampini    Collective
8900c7d97c5SJed Brown 
8910c7d97c5SJed Brown    Input Parameters:
8920c7d97c5SJed Brown +  pc - the preconditioning context
89382ba6b80SStefano Zampini -  NeumannBoundaries - parallel IS defining the subdomain part of Neumann boundaries (in local ordering)
8940c7d97c5SJed Brown 
8950c7d97c5SJed Brown    Level: intermediate
8960c7d97c5SJed Brown 
8970c7d97c5SJed Brown    Notes:
8980c7d97c5SJed Brown 
8990f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetNeumannBoundaries()
9000c7d97c5SJed Brown @*/
90182ba6b80SStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc,IS NeumannBoundaries)
9020c7d97c5SJed Brown {
9030c7d97c5SJed Brown   PetscErrorCode ierr;
9040c7d97c5SJed Brown 
9050c7d97c5SJed Brown   PetscFunctionBegin;
9060c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
9070c7d97c5SJed Brown   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
90882ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
90982ba6b80SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundariesLocal_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
91053cdbc3dSStefano Zampini   PetscFunctionReturn(0);
91153cdbc3dSStefano Zampini }
91253cdbc3dSStefano Zampini 
913da1bb401SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
914da1bb401SStefano Zampini {
915da1bb401SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
916da1bb401SStefano Zampini 
917da1bb401SStefano Zampini   PetscFunctionBegin;
918da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
919da1bb401SStefano Zampini   PetscFunctionReturn(0);
920da1bb401SStefano Zampini }
9211e6b0712SBarry Smith 
922da1bb401SStefano Zampini /*@
923785d1243SStefano Zampini  PCBDDCGetDirichletBoundaries - Get parallel IS for Dirichlet boundaries
924da1bb401SStefano Zampini 
925785d1243SStefano Zampini    Collective
926785d1243SStefano Zampini 
927785d1243SStefano Zampini    Input Parameters:
928785d1243SStefano Zampini .  pc - the preconditioning context
929785d1243SStefano Zampini 
930785d1243SStefano Zampini    Output Parameters:
931785d1243SStefano Zampini .  DirichletBoundaries - index set defining the Dirichlet boundaries
932785d1243SStefano Zampini 
933785d1243SStefano Zampini    Level: intermediate
934785d1243SStefano Zampini 
9350f202f7eSStefano Zampini    Notes:
9360f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetDirichletBoundaries
937785d1243SStefano Zampini 
938785d1243SStefano Zampini .seealso: PCBDDC
939785d1243SStefano Zampini @*/
940785d1243SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
941785d1243SStefano Zampini {
942785d1243SStefano Zampini   PetscErrorCode ierr;
943785d1243SStefano Zampini 
944785d1243SStefano Zampini   PetscFunctionBegin;
945785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
946785d1243SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
947785d1243SStefano Zampini   PetscFunctionReturn(0);
948785d1243SStefano Zampini }
949785d1243SStefano Zampini 
950785d1243SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc,IS *DirichletBoundaries)
951785d1243SStefano Zampini {
952785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
953785d1243SStefano Zampini 
954785d1243SStefano Zampini   PetscFunctionBegin;
955785d1243SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundariesLocal;
956785d1243SStefano Zampini   PetscFunctionReturn(0);
957785d1243SStefano Zampini }
958785d1243SStefano Zampini 
959da1bb401SStefano Zampini /*@
96082ba6b80SStefano Zampini  PCBDDCGetDirichletBoundariesLocal - Get parallel IS for Dirichlet boundaries (in local ordering)
961da1bb401SStefano Zampini 
962785d1243SStefano Zampini    Collective
963da1bb401SStefano Zampini 
964da1bb401SStefano Zampini    Input Parameters:
96528509bceSStefano Zampini .  pc - the preconditioning context
966da1bb401SStefano Zampini 
967da1bb401SStefano Zampini    Output Parameters:
96828509bceSStefano Zampini .  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
969da1bb401SStefano Zampini 
970da1bb401SStefano Zampini    Level: intermediate
971da1bb401SStefano Zampini 
972da1bb401SStefano Zampini    Notes:
9730f202f7eSStefano 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).
9740f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
975da1bb401SStefano Zampini 
976da1bb401SStefano Zampini .seealso: PCBDDC
977da1bb401SStefano Zampini @*/
97882ba6b80SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc,IS *DirichletBoundaries)
979da1bb401SStefano Zampini {
980da1bb401SStefano Zampini   PetscErrorCode ierr;
981da1bb401SStefano Zampini 
982da1bb401SStefano Zampini   PetscFunctionBegin;
983da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
98482ba6b80SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundariesLocal_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
985da1bb401SStefano Zampini   PetscFunctionReturn(0);
986da1bb401SStefano Zampini }
9871e6b0712SBarry Smith 
98853cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
98953cdbc3dSStefano Zampini {
99053cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
99153cdbc3dSStefano Zampini 
99253cdbc3dSStefano Zampini   PetscFunctionBegin;
99353cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
99453cdbc3dSStefano Zampini   PetscFunctionReturn(0);
99553cdbc3dSStefano Zampini }
9961e6b0712SBarry Smith 
99753cdbc3dSStefano Zampini /*@
998785d1243SStefano Zampini  PCBDDCGetNeumannBoundaries - Get parallel IS for Neumann boundaries
99953cdbc3dSStefano Zampini 
1000785d1243SStefano Zampini    Collective
1001785d1243SStefano Zampini 
1002785d1243SStefano Zampini    Input Parameters:
1003785d1243SStefano Zampini .  pc - the preconditioning context
1004785d1243SStefano Zampini 
1005785d1243SStefano Zampini    Output Parameters:
1006785d1243SStefano Zampini .  NeumannBoundaries - index set defining the Neumann boundaries
1007785d1243SStefano Zampini 
1008785d1243SStefano Zampini    Level: intermediate
1009785d1243SStefano Zampini 
10100f202f7eSStefano Zampini    Notes:
10110f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetNeumannBoundaries
1012785d1243SStefano Zampini 
1013785d1243SStefano Zampini .seealso: PCBDDC
1014785d1243SStefano Zampini @*/
1015785d1243SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
1016785d1243SStefano Zampini {
1017785d1243SStefano Zampini   PetscErrorCode ierr;
1018785d1243SStefano Zampini 
1019785d1243SStefano Zampini   PetscFunctionBegin;
1020785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1021785d1243SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
1022785d1243SStefano Zampini   PetscFunctionReturn(0);
1023785d1243SStefano Zampini }
1024785d1243SStefano Zampini 
1025785d1243SStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc,IS *NeumannBoundaries)
1026785d1243SStefano Zampini {
1027785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1028785d1243SStefano Zampini 
1029785d1243SStefano Zampini   PetscFunctionBegin;
1030785d1243SStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundariesLocal;
1031785d1243SStefano Zampini   PetscFunctionReturn(0);
1032785d1243SStefano Zampini }
1033785d1243SStefano Zampini 
103453cdbc3dSStefano Zampini /*@
103582ba6b80SStefano Zampini  PCBDDCGetNeumannBoundariesLocal - Get parallel IS for Neumann boundaries (in local ordering)
103653cdbc3dSStefano Zampini 
1037785d1243SStefano Zampini    Collective
103853cdbc3dSStefano Zampini 
103953cdbc3dSStefano Zampini    Input Parameters:
104028509bceSStefano Zampini .  pc - the preconditioning context
104153cdbc3dSStefano Zampini 
104253cdbc3dSStefano Zampini    Output Parameters:
104328509bceSStefano Zampini .  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
104453cdbc3dSStefano Zampini 
104553cdbc3dSStefano Zampini    Level: intermediate
104653cdbc3dSStefano Zampini 
104753cdbc3dSStefano Zampini    Notes:
10480f202f7eSStefano 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).
10490f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
105053cdbc3dSStefano Zampini 
105153cdbc3dSStefano Zampini .seealso: PCBDDC
105253cdbc3dSStefano Zampini @*/
105382ba6b80SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc,IS *NeumannBoundaries)
105453cdbc3dSStefano Zampini {
105553cdbc3dSStefano Zampini   PetscErrorCode ierr;
105653cdbc3dSStefano Zampini 
105753cdbc3dSStefano Zampini   PetscFunctionBegin;
105853cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
105982ba6b80SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundariesLocal_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
10600c7d97c5SJed Brown   PetscFunctionReturn(0);
10610c7d97c5SJed Brown }
10621e6b0712SBarry Smith 
10631a83f524SJed Brown static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
106436e030ebSStefano Zampini {
106536e030ebSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1066da1bb401SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
106756282151SStefano Zampini   PetscBool      same_data = PETSC_FALSE;
1068da1bb401SStefano Zampini   PetscErrorCode ierr;
106936e030ebSStefano Zampini 
107036e030ebSStefano Zampini   PetscFunctionBegin;
10718687889aSStefano Zampini   if (!nvtxs) {
107204194a47SStefano Zampini     if (copymode == PETSC_OWN_POINTER) {
107304194a47SStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
107404194a47SStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
107504194a47SStefano Zampini     }
10768687889aSStefano Zampini     ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
10778687889aSStefano Zampini     PetscFunctionReturn(0);
10788687889aSStefano Zampini   }
107966da6bd7Sstefano_zampini   if (mat_graph->nvtxs == nvtxs && mat_graph->freecsr) { /* we own the data */
108056282151SStefano Zampini     if (mat_graph->xadj == xadj && mat_graph->adjncy == adjncy) same_data = PETSC_TRUE;
108156282151SStefano Zampini     if (!same_data && mat_graph->xadj[nvtxs] == xadj[nvtxs]) {
10822d505d7fSStefano Zampini       ierr = PetscMemcmp(xadj,mat_graph->xadj,(nvtxs+1)*sizeof(PetscInt),&same_data);CHKERRQ(ierr);
10832d505d7fSStefano Zampini       if (same_data) {
10842d505d7fSStefano Zampini         ierr = PetscMemcmp(adjncy,mat_graph->adjncy,xadj[nvtxs]*sizeof(PetscInt),&same_data);CHKERRQ(ierr);
10852d505d7fSStefano Zampini       }
108656282151SStefano Zampini     }
108756282151SStefano Zampini   }
108856282151SStefano Zampini   if (!same_data) {
1089674ae819SStefano Zampini     /* free old CSR */
1090674ae819SStefano Zampini     ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
1091674ae819SStefano Zampini     /* get CSR into graph structure */
1092da1bb401SStefano Zampini     if (copymode == PETSC_COPY_VALUES) {
1093854ce69bSBarry Smith       ierr = PetscMalloc1(nvtxs+1,&mat_graph->xadj);CHKERRQ(ierr);
1094785e854fSJed Brown       ierr = PetscMalloc1(xadj[nvtxs],&mat_graph->adjncy);CHKERRQ(ierr);
1095674ae819SStefano Zampini       ierr = PetscMemcpy(mat_graph->xadj,xadj,(nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
1096674ae819SStefano Zampini       ierr = PetscMemcpy(mat_graph->adjncy,adjncy,xadj[nvtxs]*sizeof(PetscInt));CHKERRQ(ierr);
1097a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1098da1bb401SStefano Zampini     } else if (copymode == PETSC_OWN_POINTER) {
10991a83f524SJed Brown       mat_graph->xadj    = (PetscInt*)xadj;
11001a83f524SJed Brown       mat_graph->adjncy  = (PetscInt*)adjncy;
1101a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1102a1dbd327SStefano Zampini     } else if (copymode == PETSC_USE_POINTER) {
1103a1dbd327SStefano Zampini       mat_graph->xadj    = (PetscInt*)xadj;
1104a1dbd327SStefano Zampini       mat_graph->adjncy  = (PetscInt*)adjncy;
1105a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_FALSE;
1106e0fe2d75SToby Isaac     } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %D",copymode);
1107575ad6abSStefano Zampini     mat_graph->nvtxs_csr = nvtxs;
110856282151SStefano Zampini     pcbddc->recompute_topography = PETSC_TRUE;
110956282151SStefano Zampini   }
111036e030ebSStefano Zampini   PetscFunctionReturn(0);
111136e030ebSStefano Zampini }
11121e6b0712SBarry Smith 
111336e030ebSStefano Zampini /*@
111454fffbccSStefano Zampini  PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local degrees of freedom.
111536e030ebSStefano Zampini 
111636e030ebSStefano Zampini    Not collective
111736e030ebSStefano Zampini 
111836e030ebSStefano Zampini    Input Parameters:
111954fffbccSStefano Zampini +  pc - the preconditioning context.
112054fffbccSStefano Zampini .  nvtxs - number of local vertices of the graph (i.e., the number of local dofs).
112154fffbccSStefano Zampini .  xadj, adjncy - the connectivity of the dofs in CSR format.
112254fffbccSStefano Zampini -  copymode - supported modes are PETSC_COPY_VALUES, PETSC_USE_POINTER or PETSC_OWN_POINTER.
112336e030ebSStefano Zampini 
112436e030ebSStefano Zampini    Level: intermediate
112536e030ebSStefano Zampini 
112695452b02SPatrick Sanan    Notes:
112795452b02SPatrick Sanan     A dof is considered connected with all local dofs if xadj[dof+1]-xadj[dof] == 1 and adjncy[xadj[dof]] is negative.
112836e030ebSStefano Zampini 
112928509bceSStefano Zampini .seealso: PCBDDC,PetscCopyMode
113036e030ebSStefano Zampini @*/
11311a83f524SJed Brown PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
113236e030ebSStefano Zampini {
1133575ad6abSStefano Zampini   void (*f)(void) = 0;
113436e030ebSStefano Zampini   PetscErrorCode ierr;
113536e030ebSStefano Zampini 
113636e030ebSStefano Zampini   PetscFunctionBegin;
113736e030ebSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
11388687889aSStefano Zampini   if (nvtxs) {
1139674ae819SStefano Zampini     PetscValidIntPointer(xadj,3);
11401633d1f0SStefano Zampini     if (xadj[nvtxs]) PetscValidIntPointer(adjncy,4);
11418687889aSStefano Zampini   }
11421a83f524SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
1143575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
1144575ad6abSStefano Zampini   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr);
1145575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
1146575ad6abSStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
1147575ad6abSStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
1148da1bb401SStefano Zampini   }
114936e030ebSStefano Zampini   PetscFunctionReturn(0);
115036e030ebSStefano Zampini }
11511e6b0712SBarry Smith 
115263602bcaSStefano Zampini static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
115363602bcaSStefano Zampini {
115463602bcaSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
115563602bcaSStefano Zampini   PetscInt       i;
115656282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
115763602bcaSStefano Zampini   PetscErrorCode ierr;
115863602bcaSStefano Zampini 
115963602bcaSStefano Zampini   PetscFunctionBegin;
116056282151SStefano Zampini   if (pcbddc->n_ISForDofsLocal == n_is) {
116156282151SStefano Zampini     for (i=0;i<n_is;i++) {
116256282151SStefano Zampini       PetscBool isequalt;
116356282151SStefano Zampini       ierr = ISEqual(ISForDofs[i],pcbddc->ISForDofsLocal[i],&isequalt);CHKERRQ(ierr);
116456282151SStefano Zampini       if (!isequalt) break;
116556282151SStefano Zampini     }
116656282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
116756282151SStefano Zampini   }
116856282151SStefano Zampini   for (i=0;i<n_is;i++) {
116956282151SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
117056282151SStefano Zampini   }
117163602bcaSStefano Zampini   /* Destroy ISes if they were already set */
117263602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
117363602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
117463602bcaSStefano Zampini   }
117563602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
117663602bcaSStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
117763602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
117863602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
117963602bcaSStefano Zampini   }
118063602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
118163602bcaSStefano Zampini   pcbddc->n_ISForDofs = 0;
118263602bcaSStefano Zampini   /* allocate space then set */
1183d02579f5SStefano Zampini   if (n_is) {
1184d02579f5SStefano Zampini     ierr = PetscMalloc1(n_is,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
1185d02579f5SStefano Zampini   }
118663602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
118763602bcaSStefano Zampini     pcbddc->ISForDofsLocal[i] = ISForDofs[i];
118863602bcaSStefano Zampini   }
118963602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = n_is;
119063602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
119156282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
119263602bcaSStefano Zampini   PetscFunctionReturn(0);
119363602bcaSStefano Zampini }
119463602bcaSStefano Zampini 
119563602bcaSStefano Zampini /*@
119663602bcaSStefano Zampini  PCBDDCSetDofsSplittingLocal - Set index sets defining fields of the local subdomain matrix
119763602bcaSStefano Zampini 
119863602bcaSStefano Zampini    Collective
119963602bcaSStefano Zampini 
120063602bcaSStefano Zampini    Input Parameters:
120163602bcaSStefano Zampini +  pc - the preconditioning context
12020f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
12030f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in local ordering
120463602bcaSStefano Zampini 
120563602bcaSStefano Zampini    Level: intermediate
120663602bcaSStefano Zampini 
12070f202f7eSStefano Zampini    Notes:
12080f202f7eSStefano Zampini      n_is should be the same among processes. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
120963602bcaSStefano Zampini 
121063602bcaSStefano Zampini .seealso: PCBDDC
121163602bcaSStefano Zampini @*/
121263602bcaSStefano Zampini PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc,PetscInt n_is, IS ISForDofs[])
121363602bcaSStefano Zampini {
121463602bcaSStefano Zampini   PetscInt       i;
121563602bcaSStefano Zampini   PetscErrorCode ierr;
121663602bcaSStefano Zampini 
121763602bcaSStefano Zampini   PetscFunctionBegin;
121863602bcaSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
121963602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
122063602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
122163602bcaSStefano Zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
122263602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
122363602bcaSStefano Zampini   }
1224e71e7a71SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplittingLocal_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
122563602bcaSStefano Zampini   PetscFunctionReturn(0);
122663602bcaSStefano Zampini }
122763602bcaSStefano Zampini 
12289c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
12299c0446d6SStefano Zampini {
12309c0446d6SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
12319c0446d6SStefano Zampini   PetscInt       i;
123256282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
12339c0446d6SStefano Zampini   PetscErrorCode ierr;
12349c0446d6SStefano Zampini 
12359c0446d6SStefano Zampini   PetscFunctionBegin;
123656282151SStefano Zampini   if (pcbddc->n_ISForDofs == n_is) {
123756282151SStefano Zampini     for (i=0;i<n_is;i++) {
123856282151SStefano Zampini       PetscBool isequalt;
123956282151SStefano Zampini       ierr = ISEqual(ISForDofs[i],pcbddc->ISForDofs[i],&isequalt);CHKERRQ(ierr);
124056282151SStefano Zampini       if (!isequalt) break;
124156282151SStefano Zampini     }
124256282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
124356282151SStefano Zampini   }
124456282151SStefano Zampini   for (i=0;i<n_is;i++) {
124556282151SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
124656282151SStefano Zampini   }
1247da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
12489c0446d6SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
12499c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
12509c0446d6SStefano Zampini   }
1251d11ae9bbSstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
125263602bcaSStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
125363602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
125463602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
125563602bcaSStefano Zampini   }
125663602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
125763602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = 0;
1258da1bb401SStefano Zampini   /* allocate space then set */
1259d02579f5SStefano Zampini   if (n_is) {
1260785e854fSJed Brown     ierr = PetscMalloc1(n_is,&pcbddc->ISForDofs);CHKERRQ(ierr);
1261d02579f5SStefano Zampini   }
12629c0446d6SStefano Zampini   for (i=0;i<n_is;i++) {
1263da1bb401SStefano Zampini     pcbddc->ISForDofs[i] = ISForDofs[i];
12649c0446d6SStefano Zampini   }
12659c0446d6SStefano Zampini   pcbddc->n_ISForDofs = n_is;
126663602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
126756282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
12689c0446d6SStefano Zampini   PetscFunctionReturn(0);
12699c0446d6SStefano Zampini }
12701e6b0712SBarry Smith 
12719c0446d6SStefano Zampini /*@
127263602bcaSStefano Zampini  PCBDDCSetDofsSplitting - Set index sets defining fields of the global matrix
12739c0446d6SStefano Zampini 
127463602bcaSStefano Zampini    Collective
12759c0446d6SStefano Zampini 
12769c0446d6SStefano Zampini    Input Parameters:
12779c0446d6SStefano Zampini +  pc - the preconditioning context
12780f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
12790f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in global ordering
12809c0446d6SStefano Zampini 
12819c0446d6SStefano Zampini    Level: intermediate
12829c0446d6SStefano Zampini 
12830f202f7eSStefano Zampini    Notes:
12840f202f7eSStefano Zampini      Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
12859c0446d6SStefano Zampini 
12869c0446d6SStefano Zampini .seealso: PCBDDC
12879c0446d6SStefano Zampini @*/
12889c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
12899c0446d6SStefano Zampini {
12902b510759SStefano Zampini   PetscInt       i;
12919c0446d6SStefano Zampini   PetscErrorCode ierr;
12929c0446d6SStefano Zampini 
12939c0446d6SStefano Zampini   PetscFunctionBegin;
12949c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
129563602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
12962b510759SStefano Zampini   for (i=0;i<n_is;i++) {
129763602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
1298a011d5a7Sstefano_zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
12992b510759SStefano Zampini   }
13009c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
13019c0446d6SStefano Zampini   PetscFunctionReturn(0);
13029c0446d6SStefano Zampini }
1303906d46d4SStefano Zampini 
1304534831adSStefano Zampini /*
1305534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
1306534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
13079c0446d6SStefano Zampini 
1308534831adSStefano Zampini    Input Parameter:
1309534831adSStefano Zampini +  pc - the preconditioner contex
1310534831adSStefano Zampini 
1311534831adSStefano Zampini    Application Interface Routine: PCPreSolve()
1312534831adSStefano Zampini 
1313534831adSStefano Zampini    Notes:
1314534831adSStefano Zampini      The interface routine PCPreSolve() is not usually called directly by
1315534831adSStefano Zampini    the user, but instead is called by KSPSolve().
1316534831adSStefano Zampini */
1317534831adSStefano Zampini static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1318534831adSStefano Zampini {
1319534831adSStefano Zampini   PetscErrorCode ierr;
1320534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1321534831adSStefano Zampini   PC_IS          *pcis = (PC_IS*)(pc->data);
13223972b0daSStefano Zampini   Vec            used_vec;
13234df7a6bfSStefano Zampini   PetscBool      iscg = PETSC_FALSE, save_rhs = PETSC_TRUE, benign_correction_computed;
1324534831adSStefano Zampini 
1325534831adSStefano Zampini   PetscFunctionBegin;
13261f4df5f7SStefano Zampini   /* if we are working with CG, one dirichlet solve can be avoided during Krylov iterations */
132785c4d303SStefano Zampini   if (ksp) {
13284df7a6bfSStefano Zampini     PetscBool isgroppcg, ispipecg, ispipelcg, ispipecgrr;
13294df7a6bfSStefano Zampini 
133085c4d303SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPCG,&iscg);CHKERRQ(ierr);
133127b6a85dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPGROPPCG,&isgroppcg);CHKERRQ(ierr);
133227b6a85dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECG,&ispipecg);CHKERRQ(ierr);
13334df7a6bfSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECG,&ispipelcg);CHKERRQ(ierr);
1334f94e96cbSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECGRR,&ispipecgrr);CHKERRQ(ierr);
13354df7a6bfSStefano Zampini     iscg = (PetscBool)(iscg || isgroppcg || ispipecg || ispipelcg || ispipecgrr);
13363bf6e316SStefano Zampini     if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || !iscg || pc->mat != pc->pmat) {
133785c4d303SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
133885c4d303SStefano Zampini     }
133985c4d303SStefano Zampini   }
13403bf6e316SStefano Zampini   if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || pc->mat != pc->pmat) {
1341fc17d649SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
1342fc17d649SStefano Zampini   }
13431f4df5f7SStefano Zampini 
134485c4d303SStefano Zampini   /* Creates parallel work vectors used in presolve */
134562a6ff1dSStefano Zampini   if (!pcbddc->original_rhs) {
134662a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
134762a6ff1dSStefano Zampini   }
134862a6ff1dSStefano Zampini   if (!pcbddc->temp_solution) {
134962a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr);
135062a6ff1dSStefano Zampini   }
13518d00608fSStefano Zampini 
135227b6a85dSStefano Zampini   pcbddc->temp_solution_used = PETSC_FALSE;
13533972b0daSStefano Zampini   if (x) {
13543972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);
13553972b0daSStefano Zampini     used_vec = x;
13568d00608fSStefano Zampini   } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */
13573972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr);
13583972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
13593972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
136027b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
1361266e20e9SStefano Zampini     ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
1362266e20e9SStefano Zampini     save_rhs = PETSC_FALSE;
1363266e20e9SStefano Zampini     pcbddc->eliminate_dirdofs = PETSC_TRUE;
13643972b0daSStefano Zampini   }
13658efcfb23SStefano Zampini 
13668efcfb23SStefano Zampini   /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */
13673972b0daSStefano Zampini   if (ksp) {
1368a0cb1b98SStefano Zampini     /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */
13698efcfb23SStefano Zampini     ierr = KSPGetInitialGuessNonzero(ksp,&pcbddc->ksp_guess_nonzero);CHKERRQ(ierr);
13708efcfb23SStefano Zampini     if (!pcbddc->ksp_guess_nonzero) {
13713972b0daSStefano Zampini       ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
13723972b0daSStefano Zampini     }
13733972b0daSStefano Zampini   }
13743308cffdSStefano Zampini 
13758d00608fSStefano Zampini   pcbddc->rhs_change = PETSC_FALSE;
13763972b0daSStefano Zampini   /* Take into account zeroed rows -> change rhs and store solution removed */
137770c64980SStefano Zampini   if (rhs && pcbddc->eliminate_dirdofs) {
13783975b054SStefano Zampini     IS dirIS = NULL;
13793975b054SStefano Zampini 
1380a07ea27aSStefano Zampini     /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */
13813975b054SStefano Zampini     ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
13823975b054SStefano Zampini     if (dirIS) {
1383906d46d4SStefano Zampini       Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
1384785d1243SStefano Zampini       PetscInt          dirsize,i,*is_indices;
13852b095fd8SStefano Zampini       PetscScalar       *array_x;
13862b095fd8SStefano Zampini       const PetscScalar *array_diagonal;
1387785d1243SStefano Zampini 
13883972b0daSStefano Zampini       ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr);
13893972b0daSStefano Zampini       ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr);
1390e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1391e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1392e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1393e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
139482ba6b80SStefano Zampini       ierr = ISGetLocalSize(dirIS,&dirsize);CHKERRQ(ierr);
13953972b0daSStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
13962b095fd8SStefano Zampini       ierr = VecGetArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
13973972b0daSStefano Zampini       ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
13982fa5cd67SKarl Rupp       for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
13993972b0daSStefano Zampini       ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
14002b095fd8SStefano Zampini       ierr = VecRestoreArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
14013972b0daSStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
1402e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1403e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
14048d00608fSStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
14051b968477SStefano Zampini       ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
14068efcfb23SStefano Zampini     }
1407a07ea27aSStefano Zampini   }
1408b76ba322SStefano Zampini 
14098efcfb23SStefano Zampini   /* remove the computed solution or the initial guess from the rhs */
14108d00608fSStefano Zampini   if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero) ) {
141127b6a85dSStefano Zampini     /* save the original rhs */
141227b6a85dSStefano Zampini     if (save_rhs) {
141327b6a85dSStefano Zampini       ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
141427b6a85dSStefano Zampini       save_rhs = PETSC_FALSE;
14158d00608fSStefano Zampini     }
14168d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
14173972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
141827b6a85dSStefano Zampini     ierr = MatMultAdd(pc->mat,used_vec,pcbddc->original_rhs,rhs);CHKERRQ(ierr);
14193972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
14208efcfb23SStefano Zampini     ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr);
142127b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
14227acc28cbSStefano Zampini     if (ksp) {
14237acc28cbSStefano Zampini       ierr = KSPSetInitialGuessNonzero(ksp,PETSC_FALSE);CHKERRQ(ierr);
14247acc28cbSStefano Zampini     }
14253308cffdSStefano Zampini   }
14268efcfb23SStefano Zampini   ierr = VecDestroy(&used_vec);CHKERRQ(ierr);
1427b76ba322SStefano Zampini 
1428fc17d649SStefano Zampini   /* compute initial vector in benign space if needed
142927b6a85dSStefano Zampini      and remove non-benign solution from the rhs */
143027b6a85dSStefano Zampini   benign_correction_computed = PETSC_FALSE;
143108af2428SStefano Zampini   if (rhs && pcbddc->benign_compute_correction && (pcbddc->benign_have_null || pcbddc->benign_apply_coarse_only)) {
14321f4df5f7SStefano Zampini     /* compute u^*_h using ideas similar to those in Xuemin Tu's PhD thesis (see Section 4.8.1)
14331f4df5f7SStefano Zampini        Recursively apply BDDC in the multilevel case */
14340369aaf7SStefano Zampini     if (!pcbddc->benign_vec) {
14350369aaf7SStefano Zampini       ierr = VecDuplicate(rhs,&pcbddc->benign_vec);CHKERRQ(ierr);
14360369aaf7SStefano Zampini     }
1437c69e9cc1SStefano Zampini     /* keep applying coarse solver unless we no longer have benign subdomains */
1438c69e9cc1SStefano Zampini     pcbddc->benign_apply_coarse_only = pcbddc->benign_have_null ? PETSC_TRUE : PETSC_FALSE;
143927b6a85dSStefano Zampini     if (!pcbddc->benign_skip_correction) {
14401dd7afcfSStefano Zampini       ierr = PCApply_BDDC(pc,rhs,pcbddc->benign_vec);CHKERRQ(ierr);
14413bca92a6SStefano Zampini       benign_correction_computed = PETSC_TRUE;
14421f4df5f7SStefano Zampini       if (pcbddc->temp_solution_used) {
14431f4df5f7SStefano Zampini         ierr = VecAXPY(pcbddc->temp_solution,1.0,pcbddc->benign_vec);CHKERRQ(ierr);
14441f4df5f7SStefano Zampini       }
14451f4df5f7SStefano Zampini       ierr = VecScale(pcbddc->benign_vec,-1.0);CHKERRQ(ierr);
144627b6a85dSStefano Zampini       /* store the original rhs if not done earlier */
144727b6a85dSStefano Zampini       if (save_rhs) {
144827b6a85dSStefano Zampini         ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
144992e3dcfbSStefano Zampini       }
145027b6a85dSStefano Zampini       if (pcbddc->rhs_change) {
14510369aaf7SStefano Zampini         ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,rhs,rhs);CHKERRQ(ierr);
145227b6a85dSStefano Zampini       } else {
145327b6a85dSStefano Zampini         ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,pcbddc->original_rhs,rhs);CHKERRQ(ierr);
145427b6a85dSStefano Zampini       }
14550369aaf7SStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
145627b6a85dSStefano Zampini     }
145727b6a85dSStefano Zampini     pcbddc->benign_apply_coarse_only = PETSC_FALSE;
14584df7a6bfSStefano Zampini   } else {
14594df7a6bfSStefano Zampini     ierr = VecDestroy(&pcbddc->benign_vec);CHKERRQ(ierr);
14600369aaf7SStefano Zampini   }
14612d4c4fecSStefano Zampini 
14622d4c4fecSStefano Zampini   /* dbg output */
1463a198735bSStefano Zampini   if (pcbddc->dbg_flag && benign_correction_computed) {
14641f4df5f7SStefano Zampini     Vec v;
1465c69e9cc1SStefano Zampini 
14661f4df5f7SStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&v);CHKERRQ(ierr);
1467c69e9cc1SStefano Zampini     if (pcbddc->ChangeOfBasisMatrix) {
14681f4df5f7SStefano Zampini       ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,v);CHKERRQ(ierr);
1469c69e9cc1SStefano Zampini     } else {
1470c69e9cc1SStefano Zampini       ierr = VecCopy(rhs,v);CHKERRQ(ierr);
1471c69e9cc1SStefano Zampini     }
14721f4df5f7SStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,v,PETSC_TRUE);CHKERRQ(ierr);
1473e0fe2d75SToby Isaac     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"LEVEL %D: is the correction benign?\n",pcbddc->current_level);CHKERRQ(ierr);
1474c69e9cc1SStefano Zampini     ierr = PetscScalarView(pcbddc->benign_n,pcbddc->benign_p0,pcbddc->dbg_viewer);CHKERRQ(ierr);
1475c69e9cc1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
14761f4df5f7SStefano Zampini     ierr = VecDestroy(&v);CHKERRQ(ierr);
14771f4df5f7SStefano Zampini   }
14780369aaf7SStefano Zampini 
14790369aaf7SStefano Zampini   /* set initial guess if using PCG */
14808ae0ca82SStefano Zampini   pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
14810369aaf7SStefano Zampini   if (x && pcbddc->use_exact_dirichlet_trick) {
14820369aaf7SStefano Zampini     ierr = VecSet(x,0.0);CHKERRQ(ierr);
14831dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
148427b6a85dSStefano Zampini       if (benign_correction_computed) { /* we have already saved the changed rhs */
14851dd7afcfSStefano Zampini         ierr = VecLockPop(pcis->vec1_global);CHKERRQ(ierr);
14861dd7afcfSStefano Zampini       } else {
14871dd7afcfSStefano Zampini         ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,pcis->vec1_global);CHKERRQ(ierr);
14881dd7afcfSStefano Zampini       }
14891dd7afcfSStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14901dd7afcfSStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14911dd7afcfSStefano Zampini     } else {
14920369aaf7SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14930369aaf7SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
14941dd7afcfSStefano Zampini     }
14950369aaf7SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1496c0decd05SBarry Smith     ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D);CHKERRQ(ierr);
14971dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
14981dd7afcfSStefano Zampini       ierr = VecSet(pcis->vec1_global,0.);CHKERRQ(ierr);
14991dd7afcfSStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15001dd7afcfSStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15011dd7afcfSStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x);CHKERRQ(ierr);
15021dd7afcfSStefano Zampini     } else {
15030369aaf7SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15040369aaf7SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
15051dd7afcfSStefano Zampini     }
15060369aaf7SStefano Zampini     if (ksp) {
15070369aaf7SStefano Zampini       ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
15080369aaf7SStefano Zampini     }
15098ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_TRUE;
1510266e20e9SStefano Zampini   } else if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior && benign_correction_computed && pcbddc->use_exact_dirichlet_trick) {
1511266e20e9SStefano Zampini     ierr = VecLockPop(pcis->vec1_global);CHKERRQ(ierr);
15120369aaf7SStefano Zampini   }
1513534831adSStefano Zampini   PetscFunctionReturn(0);
1514534831adSStefano Zampini }
1515906d46d4SStefano Zampini 
1516534831adSStefano Zampini /*
1517534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
1518534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
1519534831adSStefano Zampini 
1520534831adSStefano Zampini    Input Parameter:
1521534831adSStefano Zampini +  pc - the preconditioner contex
1522534831adSStefano Zampini 
1523534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
1524534831adSStefano Zampini 
1525534831adSStefano Zampini    Notes:
1526534831adSStefano Zampini      The interface routine PCPostSolve() is not usually called directly by
1527534831adSStefano Zampini      the user, but instead is called by KSPSolve().
1528534831adSStefano Zampini */
1529534831adSStefano Zampini static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1530534831adSStefano Zampini {
1531534831adSStefano Zampini   PetscErrorCode ierr;
1532534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1533534831adSStefano Zampini 
1534534831adSStefano Zampini   PetscFunctionBegin;
15353972b0daSStefano Zampini   /* add solution removed in presolve */
15366bcfc461SStefano Zampini   if (x && pcbddc->rhs_change) {
153727b6a85dSStefano Zampini     if (pcbddc->temp_solution_used) {
15383425bc38SStefano Zampini       ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr);
1539af140850Sstefano_zampini     } else if (pcbddc->benign_compute_correction && pcbddc->benign_vec) {
154027b6a85dSStefano Zampini       ierr = VecAXPY(x,-1.0,pcbddc->benign_vec);CHKERRQ(ierr);
15413425bc38SStefano Zampini     }
1542af140850Sstefano_zampini     /* restore to original state (not for FETI-DP) */
1543af140850Sstefano_zampini     if (ksp) pcbddc->temp_solution_used = PETSC_FALSE;
154427b6a85dSStefano Zampini   }
154527b6a85dSStefano Zampini 
1546266e20e9SStefano Zampini   /* restore rhs to its original state (not needed for FETI-DP) */
15478d00608fSStefano Zampini   if (rhs && pcbddc->rhs_change) {
154827b6a85dSStefano Zampini     ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
15498d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_FALSE;
1550af140850Sstefano_zampini   }
15518efcfb23SStefano Zampini   /* restore ksp guess state */
15528efcfb23SStefano Zampini   if (ksp) {
15538efcfb23SStefano Zampini     ierr = KSPSetInitialGuessNonzero(ksp,pcbddc->ksp_guess_nonzero);CHKERRQ(ierr);
15548ae0ca82SStefano Zampini     /* reset flag for exact dirichlet trick */
15558ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
1556af140850Sstefano_zampini   }
1557534831adSStefano Zampini   PetscFunctionReturn(0);
1558534831adSStefano Zampini }
1559af140850Sstefano_zampini 
15600c7d97c5SJed Brown /*
15610c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
15620c7d97c5SJed Brown                   by setting data structures and options.
15630c7d97c5SJed Brown 
15640c7d97c5SJed Brown    Input Parameter:
156553cdbc3dSStefano Zampini +  pc - the preconditioner context
15660c7d97c5SJed Brown 
15670c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
15680c7d97c5SJed Brown 
15690c7d97c5SJed Brown    Notes:
15700c7d97c5SJed Brown      The interface routine PCSetUp() is not usually called directly by
15710c7d97c5SJed Brown      the user, but instead is called by PCApply() if necessary.
15720c7d97c5SJed Brown */
157353cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
15740c7d97c5SJed Brown {
15750c7d97c5SJed Brown   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1576c703fcc7SStefano Zampini   PCBDDCSubSchurs sub_schurs;
15775e8657edSStefano Zampini   Mat_IS*         matis;
157808122e43SStefano Zampini   MatNullSpace    nearnullspace;
157935509ce9Sstefano_zampini   Mat             lA;
158035509ce9Sstefano_zampini   IS              lP,zerodiag = NULL;
158191e8d312SStefano Zampini   PetscInt        nrows,ncols;
158286bfa4cfSStefano Zampini   PetscMPIInt     size;
1583c703fcc7SStefano Zampini   PetscBool       computesubschurs;
15848de1fae6SStefano Zampini   PetscBool       computeconstraintsmatrix;
15853b03f7bbSStefano Zampini   PetscBool       new_nearnullspace_provided,ismatis,rl;
1586c703fcc7SStefano Zampini   PetscErrorCode  ierr;
15870c7d97c5SJed Brown 
15880c7d97c5SJed Brown   PetscFunctionBegin;
15895e8657edSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATIS,&ismatis);CHKERRQ(ierr);
15906c4ed002SBarry Smith   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner requires matrix of type MATIS");
159191e8d312SStefano Zampini   ierr = MatGetSize(pc->pmat,&nrows,&ncols);CHKERRQ(ierr);
15926c4ed002SBarry Smith   if (nrows != ncols) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCBDDC preconditioner requires a square preconditioning matrix");
159386bfa4cfSStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
159486bfa4cfSStefano Zampini 
15955e8657edSStefano Zampini   matis = (Mat_IS*)pc->pmat->data;
1596f4ddd8eeSStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */
15973b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
159871582508SStefano Zampini      Also, BDDC builds its own KSP for the Dirichlet problem */
15993b03f7bbSStefano Zampini   rl = pcbddc->recompute_topography;
16003b03f7bbSStefano Zampini   if (!pc->setupcalled || pc->flag == DIFFERENT_NONZERO_PATTERN) rl = PETSC_TRUE;
16013b03f7bbSStefano Zampini   ierr = MPIU_Allreduce(&rl,&pcbddc->recompute_topography,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1602c83e1ba7SStefano Zampini   if (pcbddc->recompute_topography) {
1603c83e1ba7SStefano Zampini     pcbddc->graphanalyzed    = PETSC_FALSE;
1604c83e1ba7SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1605c83e1ba7SStefano Zampini   } else {
16068de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_FALSE;
1607c83e1ba7SStefano Zampini   }
1608b087196eSStefano Zampini 
1609b087196eSStefano Zampini   /* check parameters' compatibility */
1610b7ab4a40SStefano Zampini   if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE;
1611bd2a564bSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_threshold[0] != 0.0 || pcbddc->adaptive_threshold[1] != 0.0);
161286bfa4cfSStefano Zampini   pcbddc->use_deluxe_scaling   = (PetscBool)(pcbddc->use_deluxe_scaling && size > 1);
161386bfa4cfSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_selection && size > 1);
1614bf3a8328SStefano Zampini   pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined);
1615862806e4SStefano Zampini   if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE;
1616862806e4SStefano Zampini 
16175a95e1ceSStefano Zampini   computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling);
161816909a7fSStefano Zampini 
161971582508SStefano Zampini   /* activate all connected components if the netflux has been requested */
1620bb05f991SStefano Zampini   if (pcbddc->compute_nonetflux) {
1621bb05f991SStefano Zampini     pcbddc->use_vertices = PETSC_TRUE;
1622bb05f991SStefano Zampini     pcbddc->use_edges    = PETSC_TRUE;
1623bb05f991SStefano Zampini     pcbddc->use_faces    = PETSC_TRUE;
1624bb05f991SStefano Zampini   }
1625bb05f991SStefano Zampini 
1626f4ddd8eeSStefano Zampini   /* Get stdout for dbg */
162770cf5478SStefano Zampini   if (pcbddc->dbg_flag) {
162870cf5478SStefano Zampini     if (!pcbddc->dbg_viewer) {
162958a03d70SStefano Zampini       pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc));
1630f4ddd8eeSStefano Zampini     }
1631d9869140SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
163258a03d70SStefano Zampini     ierr = PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
1633f4ddd8eeSStefano Zampini   }
1634f4ddd8eeSStefano Zampini 
1635c703fcc7SStefano Zampini   /* process topology information */
163643371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_Topology[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
163771582508SStefano Zampini   if (pcbddc->recompute_topography) {
163871582508SStefano Zampini     ierr = PCBDDCComputeLocalTopologyInfo(pc);CHKERRQ(ierr);
1639c703fcc7SStefano Zampini     if (pcbddc->discretegradient) {
1640a13144ffSStefano Zampini       ierr = PCBDDCNedelecSupport(pc);CHKERRQ(ierr);
1641a13144ffSStefano Zampini     }
1642c703fcc7SStefano Zampini   }
1643*4f819b78SStefano Zampini   if (pcbddc->corner_selected) pcbddc->use_vertices = PETSC_TRUE;
1644a13144ffSStefano Zampini 
1645c703fcc7SStefano Zampini   /* change basis if requested by the user */
16465e8657edSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) {
16475e8657edSStefano Zampini     /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */
16485e8657edSStefano Zampini     pcbddc->use_change_of_basis = PETSC_FALSE;
16495e8657edSStefano Zampini     ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
16505e8657edSStefano Zampini   } else {
1651b96c3477SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
16525e8657edSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
16535e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
1654d16cbb6bSStefano Zampini   }
1655d16cbb6bSStefano Zampini 
16564f1b2e48SStefano Zampini   /*
1657c703fcc7SStefano Zampini      Compute change of basis on local pressures (aka zerodiag dofs) with the benign trick
16584f1b2e48SStefano Zampini      This should come earlier then PCISSetUp for extracting the correct subdomain matrices
16594f1b2e48SStefano Zampini   */
16601dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
1661d16cbb6bSStefano Zampini   if (pcbddc->benign_saddle_point) {
16629f47a83aSStefano Zampini     PC_IS* pcis = (PC_IS*)pc->data;
16639f47a83aSStefano Zampini 
166405b28244SStefano Zampini     if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE;
16653b03f7bbSStefano Zampini     /* detect local saddle point and change the basis in pcbddc->local_mat */
16663b03f7bbSStefano Zampini     ierr = PCBDDCBenignDetectSaddlePoint(pc,(PetscBool)(!pcbddc->recompute_topography),&zerodiag);CHKERRQ(ierr);
1667a3df083aSStefano Zampini     /* pop B0 mat from local mat */
1668c263805aSStefano Zampini     ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
16691dd7afcfSStefano Zampini     /* give pcis a hint to not reuse submatrices during PCISCreate */
16701dd7afcfSStefano Zampini     if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) {
16711dd7afcfSStefano Zampini       if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) {
16721dd7afcfSStefano Zampini         pcis->reusesubmatrices = PETSC_FALSE;
16731dd7afcfSStefano Zampini       } else {
1674a3df083aSStefano Zampini         pcis->reusesubmatrices = PETSC_TRUE;
16751dd7afcfSStefano Zampini       }
1676a3df083aSStefano Zampini     } else {
16779f47a83aSStefano Zampini       pcis->reusesubmatrices = PETSC_FALSE;
1678674ae819SStefano Zampini     }
1679a3df083aSStefano Zampini   }
168027b6a85dSStefano Zampini 
16818037d520SStefano Zampini   /* propagate relevant information */
168206a4e24aSStefano Zampini   if (matis->A->symmetric_set) {
168306a4e24aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
168406a4e24aSStefano Zampini   }
168506a4e24aSStefano Zampini   if (matis->A->spd_set) {
168606a4e24aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SPD,matis->A->spd);CHKERRQ(ierr);
168706a4e24aSStefano Zampini   }
1688e496cd5dSStefano Zampini 
16895e8657edSStefano Zampini   /* Set up all the "iterative substructuring" common block without computing solvers */
16905e8657edSStefano Zampini   {
16915e8657edSStefano Zampini     Mat temp_mat;
16925e8657edSStefano Zampini 
16935e8657edSStefano Zampini     temp_mat = matis->A;
16945e8657edSStefano Zampini     matis->A = pcbddc->local_mat;
1695d9869140SStefano Zampini     ierr = PCISSetUp(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
16965e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
16975e8657edSStefano Zampini     matis->A = temp_mat;
16985e8657edSStefano Zampini   }
1699684f6988SStefano Zampini 
170081d14e9dSStefano Zampini   /* Analyze interface */
170164ac59b8SStefano Zampini   if (!pcbddc->graphanalyzed) {
1702674ae819SStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
17038de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1704345ecf6cSStefano Zampini     if (pcbddc->adaptive_selection && !pcbddc->use_deluxe_scaling && !pcbddc->mat_graph->twodim) {
17054247aa23Sstefano_zampini       SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot compute the adaptive primal space for a problem with 3D edges without deluxe scaling");
1706345ecf6cSStefano Zampini     }
1707a198735bSStefano Zampini     if (pcbddc->compute_nonetflux) {
1708669cc0f4SStefano Zampini       MatNullSpace nnfnnsp;
1709669cc0f4SStefano Zampini 
171021ef3d20SStefano Zampini       if (!pcbddc->divudotp) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Missing divudotp operator");
17118ae0ca82SStefano Zampini       ierr = PCBDDCComputeNoNetFlux(pc->pmat,pcbddc->divudotp,pcbddc->divudotp_trans,pcbddc->divudotp_vl2l,pcbddc->mat_graph,&nnfnnsp);CHKERRQ(ierr);
171271582508SStefano Zampini       /* TODO what if a nearnullspace is already attached? */
17138037d520SStefano Zampini       if (nnfnnsp) {
1714669cc0f4SStefano Zampini         ierr = MatSetNearNullSpace(pc->pmat,nnfnnsp);CHKERRQ(ierr);
1715669cc0f4SStefano Zampini         ierr = MatNullSpaceDestroy(&nnfnnsp);CHKERRQ(ierr);
1716669cc0f4SStefano Zampini       }
1717674ae819SStefano Zampini     }
17188037d520SStefano Zampini   }
171943371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_Topology[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
1720fb8d54d4SStefano Zampini 
17215408967cSStefano Zampini   /* check existence of a divergence free extension, i.e.
17225408967cSStefano Zampini      b(v_I,p_0) = 0 for all v_I (raise error if not).
17235408967cSStefano Zampini      Also, check that PCBDDCBenignGetOrSetP0 works */
1724ff1f7e73Sstefano_zampini   if (pcbddc->benign_saddle_point && pcbddc->dbg_flag > 1) {
17255408967cSStefano Zampini     ierr = PCBDDCBenignCheck(pc,zerodiag);CHKERRQ(ierr);
172609f581a4SStefano Zampini   }
17274f1b2e48SStefano Zampini   ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
172806f24817SStefano Zampini 
1729b96c3477SStefano Zampini   /* Setup local dirichlet solver ksp_D and sub_schurs solvers */
1730c703fcc7SStefano Zampini   if (computesubschurs && pcbddc->recompute_topography) {
173108122e43SStefano Zampini     ierr = PCBDDCInitSubSchurs(pc);CHKERRQ(ierr);
1732b1b3d7a2SStefano Zampini   }
17339d54b7f4SStefano Zampini   /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/
17349d54b7f4SStefano Zampini   if (!pcbddc->use_deluxe_scaling) {
17359d54b7f4SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
17369d54b7f4SStefano Zampini   }
1737c703fcc7SStefano Zampini 
1738c703fcc7SStefano Zampini   /* finish setup solvers and do adaptive selection of constraints */
1739b334f244SStefano Zampini   sub_schurs = pcbddc->sub_schurs;
1740b334f244SStefano Zampini   if (sub_schurs && sub_schurs->schur_explicit) {
17412070dbb6SStefano Zampini     if (computesubschurs) {
174208122e43SStefano Zampini       ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
17432070dbb6SStefano Zampini     }
1744d5574798SStefano Zampini     ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
1745d5574798SStefano Zampini   } else {
1746d5574798SStefano Zampini     ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
17472070dbb6SStefano Zampini     if (computesubschurs) {
1748d5574798SStefano Zampini       ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
1749d5574798SStefano Zampini     }
17502070dbb6SStefano Zampini   }
175108122e43SStefano Zampini   if (pcbddc->adaptive_selection) {
175208122e43SStefano Zampini     ierr = PCBDDCAdaptiveSelection(pc);CHKERRQ(ierr);
17538de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1754b7eb3628SStefano Zampini   }
1755684f6988SStefano Zampini 
1756f4ddd8eeSStefano Zampini   /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */
1757fb8d54d4SStefano Zampini   new_nearnullspace_provided = PETSC_FALSE;
1758f4ddd8eeSStefano Zampini   ierr = MatGetNearNullSpace(pc->pmat,&nearnullspace);CHKERRQ(ierr);
1759f4ddd8eeSStefano Zampini   if (pcbddc->onearnullspace) { /* already used nearnullspace */
1760f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* near null space attached to mat has been destroyed */
1761f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1762f4ddd8eeSStefano Zampini     } else {
1763f4ddd8eeSStefano Zampini       /* determine if the two nullspaces are different (should be lightweight) */
1764f4ddd8eeSStefano Zampini       if (nearnullspace != pcbddc->onearnullspace) {
1765f4ddd8eeSStefano Zampini         new_nearnullspace_provided = PETSC_TRUE;
1766165b64e2SStefano Zampini       } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */
1767f4ddd8eeSStefano Zampini         PetscInt         i;
1768165b64e2SStefano Zampini         const Vec        *nearnullvecs;
1769165b64e2SStefano Zampini         PetscObjectState state;
1770165b64e2SStefano Zampini         PetscInt         nnsp_size;
1771165b64e2SStefano Zampini         ierr = MatNullSpaceGetVecs(nearnullspace,NULL,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
1772f4ddd8eeSStefano Zampini         for (i=0;i<nnsp_size;i++) {
1773f4ddd8eeSStefano Zampini           ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&state);CHKERRQ(ierr);
1774165b64e2SStefano Zampini           if (pcbddc->onearnullvecs_state[i] != state) {
1775f4ddd8eeSStefano Zampini             new_nearnullspace_provided = PETSC_TRUE;
1776f4ddd8eeSStefano Zampini             break;
1777f4ddd8eeSStefano Zampini           }
1778f4ddd8eeSStefano Zampini         }
1779f4ddd8eeSStefano Zampini       }
1780f4ddd8eeSStefano Zampini     }
1781f4ddd8eeSStefano Zampini   } else {
1782f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* both nearnullspaces are null */
1783f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_FALSE;
1784f4ddd8eeSStefano Zampini     } else { /* nearnullspace attached later */
1785f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1786f4ddd8eeSStefano Zampini     }
1787f4ddd8eeSStefano Zampini   }
1788f4ddd8eeSStefano Zampini 
1789f4ddd8eeSStefano Zampini   /* Setup constraints and related work vectors */
1790727cdba6SStefano Zampini   /* reset primal space flags */
179143371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_LocalWork[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
1792f4ddd8eeSStefano Zampini   pcbddc->new_primal_space = PETSC_FALSE;
1793727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_FALSE;
17948de1fae6SStefano Zampini   if (computeconstraintsmatrix || new_nearnullspace_provided) {
1795727cdba6SStefano Zampini     /* It also sets the primal space flags */
1796674ae819SStefano Zampini     ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr);
17979543d0ffSStefano Zampini   }
1798e7b262bdSStefano Zampini   /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */
1799f4ddd8eeSStefano Zampini   ierr = PCBDDCSetUpLocalWorkVectors(pc);CHKERRQ(ierr);
18005e8657edSStefano Zampini 
18015e8657edSStefano Zampini   if (pcbddc->use_change_of_basis) {
18025e8657edSStefano Zampini     PC_IS *pcis = (PC_IS*)(pc->data);
18035e8657edSStefano Zampini 
18045e8657edSStefano Zampini     ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
18054f1b2e48SStefano Zampini     if (pcbddc->benign_change) {
18061dd7afcfSStefano Zampini       ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
1807c263805aSStefano Zampini       /* pop B0 from pcbddc->local_mat */
1808c263805aSStefano Zampini       ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
1809c263805aSStefano Zampini     }
18105e8657edSStefano Zampini     /* get submatrices */
18115e8657edSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
18125e8657edSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
18135e8657edSStefano Zampini     ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);
18147dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB);CHKERRQ(ierr);
18157dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr);
18167dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr);
18173975b054SStefano Zampini     /* set flag in pcis to not reuse submatrices during PCISCreate */
18183975b054SStefano Zampini     pcis->reusesubmatrices = PETSC_FALSE;
18199c6a02ceSStefano Zampini   } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) {
1820b96c3477SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
18215e8657edSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
18225e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
18235e8657edSStefano Zampini   }
182435509ce9Sstefano_zampini 
182535509ce9Sstefano_zampini   /* interface pressure block row for B_C */
182635509ce9Sstefano_zampini   ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP" ,(PetscObject*)&lP);CHKERRQ(ierr);
182735509ce9Sstefano_zampini   ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA);CHKERRQ(ierr);
182835509ce9Sstefano_zampini   if (lA && lP) {
182935509ce9Sstefano_zampini     PC_IS*    pcis = (PC_IS*)pc->data;
183035509ce9Sstefano_zampini     Mat       B_BI,B_BB,Bt_BI,Bt_BB;
183135509ce9Sstefano_zampini     PetscBool issym;
183235509ce9Sstefano_zampini     ierr = MatIsSymmetric(lA,PETSC_SMALL,&issym);CHKERRQ(ierr);
18336cc1294bSstefano_zampini     if (issym) {
18347dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI);CHKERRQ(ierr);
18357dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB);CHKERRQ(ierr);
183635509ce9Sstefano_zampini       ierr = MatCreateTranspose(B_BI,&Bt_BI);CHKERRQ(ierr);
183735509ce9Sstefano_zampini       ierr = MatCreateTranspose(B_BB,&Bt_BB);CHKERRQ(ierr);
183835509ce9Sstefano_zampini     } else {
18397dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI);CHKERRQ(ierr);
18407dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB);CHKERRQ(ierr);
18417dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,pcis->is_I_local,lP,MAT_INITIAL_MATRIX,&Bt_BI);CHKERRQ(ierr);
18427dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,pcis->is_B_local,lP,MAT_INITIAL_MATRIX,&Bt_BB);CHKERRQ(ierr);
184335509ce9Sstefano_zampini     }
184435509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BI",(PetscObject)B_BI);CHKERRQ(ierr);
184535509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BB",(PetscObject)B_BB);CHKERRQ(ierr);
184635509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BI",(PetscObject)Bt_BI);CHKERRQ(ierr);
184735509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BB",(PetscObject)Bt_BB);CHKERRQ(ierr);
184835509ce9Sstefano_zampini     ierr = MatDestroy(&B_BI);CHKERRQ(ierr);
184935509ce9Sstefano_zampini     ierr = MatDestroy(&B_BB);CHKERRQ(ierr);
185035509ce9Sstefano_zampini     ierr = MatDestroy(&Bt_BI);CHKERRQ(ierr);
185135509ce9Sstefano_zampini     ierr = MatDestroy(&Bt_BB);CHKERRQ(ierr);
185235509ce9Sstefano_zampini   }
185343371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_LocalWork[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
185435509ce9Sstefano_zampini 
1855b96c3477SStefano Zampini   /* SetUp coarse and local Neumann solvers */
185699cc7994SStefano Zampini   ierr = PCBDDCSetUpSolvers(pc);CHKERRQ(ierr);
1857b96c3477SStefano Zampini   /* SetUp Scaling operator */
18589d54b7f4SStefano Zampini   if (pcbddc->use_deluxe_scaling) {
1859674ae819SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
18600c7d97c5SJed Brown   }
1861c703fcc7SStefano Zampini 
18621dd7afcfSStefano Zampini   /* mark topography as done */
186356282151SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
18640369aaf7SStefano Zampini 
18651dd7afcfSStefano Zampini   /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */
18661dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_FALSE);CHKERRQ(ierr);
18671dd7afcfSStefano Zampini 
186858a03d70SStefano Zampini   if (pcbddc->dbg_flag) {
186958a03d70SStefano Zampini     ierr = PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
1870d9869140SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
18712b510759SStefano Zampini   }
18720c7d97c5SJed Brown   PetscFunctionReturn(0);
18730c7d97c5SJed Brown }
18740c7d97c5SJed Brown 
18750c7d97c5SJed Brown /*
187650efa1b5SStefano Zampini    PCApply_BDDC - Applies the BDDC operator to a vector.
18770c7d97c5SJed Brown 
18780c7d97c5SJed Brown    Input Parameters:
18790f202f7eSStefano Zampini +  pc - the preconditioner context
18800f202f7eSStefano Zampini -  r - input vector (global)
18810c7d97c5SJed Brown 
18820c7d97c5SJed Brown    Output Parameter:
18830c7d97c5SJed Brown .  z - output vector (global)
18840c7d97c5SJed Brown 
18850c7d97c5SJed Brown    Application Interface Routine: PCApply()
18860c7d97c5SJed Brown  */
188753cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
18880c7d97c5SJed Brown {
18890c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
18900c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1891b3338236SStefano Zampini   Mat               lA = NULL;
1892b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
18930c7d97c5SJed Brown   PetscErrorCode    ierr;
18943b03a366Sstefano_zampini   const PetscScalar one = 1.0;
18953b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
18962617d88aSStefano Zampini   const PetscScalar zero = 0.0;
18970c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
18980c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
1899b097fa66SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */
19000c7d97c5SJed Brown 
19010c7d97c5SJed Brown   PetscFunctionBegin;
1902f3d41395Sstefano_zampini   ierr = PetscCitationsRegister(citation,&cited);CHKERRQ(ierr);
1903b3338236SStefano Zampini   if (pcbddc->switch_static) {
1904b3338236SStefano Zampini     ierr = MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat,&lA);CHKERRQ(ierr);
1905b3338236SStefano Zampini   }
1906b3338236SStefano Zampini 
19071dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
19081dd7afcfSStefano Zampini     Vec swap;
190927b6a85dSStefano Zampini 
191027b6a85dSStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
19111dd7afcfSStefano Zampini     swap = pcbddc->work_change;
19121dd7afcfSStefano Zampini     pcbddc->work_change = r;
19131dd7afcfSStefano Zampini     r = swap;
19141dd7afcfSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
19159cc2a9b1Sstefano_zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) {
19161dd7afcfSStefano Zampini       ierr = VecCopy(r,pcis->vec1_global);CHKERRQ(ierr);
19171dd7afcfSStefano Zampini       ierr = VecLockPush(pcis->vec1_global);CHKERRQ(ierr);
19181dd7afcfSStefano Zampini     }
19191dd7afcfSStefano Zampini   }
192027b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
1921015636ebSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
1922efc2fbd9SStefano Zampini   }
19238ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1924b097fa66SStefano Zampini     ierr = VecCopy(r,z);CHKERRQ(ierr);
19250c7d97c5SJed Brown     /* First Dirichlet solve */
19260c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19270c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19280c7d97c5SJed Brown     /*
19290c7d97c5SJed Brown       Assembling right hand side for BDDC operator
1930b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
1931674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
19320c7d97c5SJed Brown     */
1933b097fa66SStefano Zampini     if (n_D) {
1934b097fa66SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1935c0decd05SBarry Smith       ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D);CHKERRQ(ierr);
19360c7d97c5SJed Brown       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
193716909a7fSStefano Zampini       if (pcbddc->switch_static) {
193816909a7fSStefano Zampini         ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
193916909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
194016909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
194116909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
1942b3338236SStefano Zampini           ierr = MatMult(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
194316909a7fSStefano Zampini         } else {
194416909a7fSStefano Zampini           ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1945b3338236SStefano Zampini           ierr = MatMult(lA,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
194616909a7fSStefano Zampini           ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
194716909a7fSStefano Zampini         }
194816909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
194916909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
195016909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
195116909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
195216909a7fSStefano Zampini       } else {
1953b097fa66SStefano Zampini         ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
195416909a7fSStefano Zampini       }
1955b097fa66SStefano Zampini     } else {
1956b097fa66SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1957b097fa66SStefano Zampini     }
19580c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
19590c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1960674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
1961b76ba322SStefano Zampini   } else {
19624fee134fSStefano Zampini     if (!pcbddc->benign_apply_coarse_only) {
1963674ae819SStefano Zampini       ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
1964b76ba322SStefano Zampini     }
19654fee134fSStefano Zampini   }
1966b76ba322SStefano Zampini 
19672617d88aSStefano Zampini   /* Apply interface preconditioner
19682617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
1969dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
19702617d88aSStefano Zampini 
1971674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
1972674ae819SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
19730c7d97c5SJed Brown 
19743b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
19750c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19760c7d97c5SJed Brown   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1977b097fa66SStefano Zampini   if (n_B) {
197816909a7fSStefano Zampini     if (pcbddc->switch_static) {
197916909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
198016909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
198116909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
198216909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
198316909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
1984b3338236SStefano Zampini         ierr = MatMult(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
198516909a7fSStefano Zampini       } else {
198616909a7fSStefano Zampini         ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1987b3338236SStefano Zampini         ierr = MatMult(lA,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
198816909a7fSStefano Zampini         ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
198916909a7fSStefano Zampini       }
199016909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
199116909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
199216909a7fSStefano Zampini     } else {
19930c7d97c5SJed Brown       ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
199416909a7fSStefano Zampini     }
199516909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
199616909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
1997b3338236SStefano Zampini       ierr = MatMult(lA,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
199816909a7fSStefano Zampini     } else {
199916909a7fSStefano Zampini       ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N);CHKERRQ(ierr);
2000b3338236SStefano Zampini       ierr = MatMult(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
200116909a7fSStefano Zampini       ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D);CHKERRQ(ierr);
200216909a7fSStefano Zampini     }
2003b097fa66SStefano Zampini   }
2004df187020SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
2005c0decd05SBarry Smith   ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec4_D);CHKERRQ(ierr);
2006efc2fbd9SStefano Zampini 
20078ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
2008b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2009b097fa66SStefano Zampini       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
2010b097fa66SStefano Zampini     } else {
2011b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
2012b097fa66SStefano Zampini     }
20130c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20140c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2015b097fa66SStefano Zampini   } else {
2016b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2017b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
2018b097fa66SStefano Zampini     } else {
2019b097fa66SStefano Zampini       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
2020b097fa66SStefano Zampini     }
2021b097fa66SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2022b097fa66SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2023b097fa66SStefano Zampini   }
202427b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
20251dd7afcfSStefano Zampini     if (pcbddc->benign_apply_coarse_only) {
20261dd7afcfSStefano Zampini       ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
20271dd7afcfSStefano Zampini     }
2028015636ebSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
2029efc2fbd9SStefano Zampini   }
20301f4df5f7SStefano Zampini 
20311dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2032f913dca9SStefano Zampini     pcbddc->work_change = r;
20331dd7afcfSStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
20341dd7afcfSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
20351dd7afcfSStefano Zampini   }
20360c7d97c5SJed Brown   PetscFunctionReturn(0);
20370c7d97c5SJed Brown }
203850efa1b5SStefano Zampini 
203950efa1b5SStefano Zampini /*
204050efa1b5SStefano Zampini    PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector.
204150efa1b5SStefano Zampini 
204250efa1b5SStefano Zampini    Input Parameters:
20430f202f7eSStefano Zampini +  pc - the preconditioner context
20440f202f7eSStefano Zampini -  r - input vector (global)
204550efa1b5SStefano Zampini 
204650efa1b5SStefano Zampini    Output Parameter:
204750efa1b5SStefano Zampini .  z - output vector (global)
204850efa1b5SStefano Zampini 
204950efa1b5SStefano Zampini    Application Interface Routine: PCApplyTranspose()
205050efa1b5SStefano Zampini  */
205150efa1b5SStefano Zampini PetscErrorCode PCApplyTranspose_BDDC(PC pc,Vec r,Vec z)
205250efa1b5SStefano Zampini {
205350efa1b5SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
205450efa1b5SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
2055b3338236SStefano Zampini   Mat               lA = NULL;
2056b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
205750efa1b5SStefano Zampini   PetscErrorCode    ierr;
205850efa1b5SStefano Zampini   const PetscScalar one = 1.0;
205950efa1b5SStefano Zampini   const PetscScalar m_one = -1.0;
206050efa1b5SStefano Zampini   const PetscScalar zero = 0.0;
206150efa1b5SStefano Zampini 
206250efa1b5SStefano Zampini   PetscFunctionBegin;
2063f3d41395Sstefano_zampini   ierr = PetscCitationsRegister(citation,&cited);CHKERRQ(ierr);
2064b3338236SStefano Zampini   if (pcbddc->switch_static) {
2065b3338236SStefano Zampini     ierr = MatISGetLocalMat(pc->useAmat ? pc->mat : pc->pmat,&lA);CHKERRQ(ierr);
2066b3338236SStefano Zampini   }
20671dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
20681dd7afcfSStefano Zampini     Vec swap;
206927b6a85dSStefano Zampini 
207027b6a85dSStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
20711dd7afcfSStefano Zampini     swap = pcbddc->work_change;
20721dd7afcfSStefano Zampini     pcbddc->work_change = r;
20731dd7afcfSStefano Zampini     r = swap;
207427b6a85dSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
20758ae0ca82SStefano Zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->exact_dirichlet_trick_app && pcbddc->change_interior) {
207627b6a85dSStefano Zampini       ierr = VecCopy(r,pcis->vec1_global);CHKERRQ(ierr);
207727b6a85dSStefano Zampini       ierr = VecLockPush(pcis->vec1_global);CHKERRQ(ierr);
20781dd7afcfSStefano Zampini     }
207927b6a85dSStefano Zampini   }
208027b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
2081537c1cdfSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
2082537c1cdfSStefano Zampini   }
20838ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
2084b097fa66SStefano Zampini     ierr = VecCopy(r,z);CHKERRQ(ierr);
208550efa1b5SStefano Zampini     /* First Dirichlet solve */
208650efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
208750efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
208850efa1b5SStefano Zampini     /*
208950efa1b5SStefano Zampini       Assembling right hand side for BDDC operator
2090b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
209150efa1b5SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
209250efa1b5SStefano Zampini     */
2093b097fa66SStefano Zampini     if (n_D) {
2094b097fa66SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
2095c0decd05SBarry Smith       ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec2_D);CHKERRQ(ierr);
209650efa1b5SStefano Zampini       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
209716909a7fSStefano Zampini       if (pcbddc->switch_static) {
209816909a7fSStefano Zampini         ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
209916909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
210016909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
210116909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
2102b3338236SStefano Zampini           ierr = MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
210316909a7fSStefano Zampini         } else {
210416909a7fSStefano Zampini           ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
2105b3338236SStefano Zampini           ierr = MatMultTranspose(lA,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
210616909a7fSStefano Zampini           ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
210716909a7fSStefano Zampini         }
210816909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
210916909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
211016909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
211116909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
211216909a7fSStefano Zampini       } else {
2113b097fa66SStefano Zampini         ierr = MatMultTranspose(pcis->A_IB,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
211416909a7fSStefano Zampini       }
2115b097fa66SStefano Zampini     } else {
2116b097fa66SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
2117b097fa66SStefano Zampini     }
211850efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
211950efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
212050efa1b5SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
212150efa1b5SStefano Zampini   } else {
212250efa1b5SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
212350efa1b5SStefano Zampini   }
212450efa1b5SStefano Zampini 
212550efa1b5SStefano Zampini   /* Apply interface preconditioner
212650efa1b5SStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
2127dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_TRUE);CHKERRQ(ierr);
212850efa1b5SStefano Zampini 
212950efa1b5SStefano Zampini   /* Apply transpose of partition of unity operator */
213050efa1b5SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
213150efa1b5SStefano Zampini 
213250efa1b5SStefano Zampini   /* Second Dirichlet solve and assembling of output */
213350efa1b5SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
213450efa1b5SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2135b097fa66SStefano Zampini   if (n_B) {
213616909a7fSStefano Zampini     if (pcbddc->switch_static) {
213716909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
213816909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
213916909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
214016909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
214116909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
2142b3338236SStefano Zampini         ierr = MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
214316909a7fSStefano Zampini       } else {
214416909a7fSStefano Zampini         ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
2145b3338236SStefano Zampini         ierr = MatMultTranspose(lA,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
214616909a7fSStefano Zampini         ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
214716909a7fSStefano Zampini       }
214816909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
214916909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
215016909a7fSStefano Zampini     } else {
215150efa1b5SStefano Zampini       ierr = MatMultTranspose(pcis->A_BI,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
215216909a7fSStefano Zampini     }
215316909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
215416909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
2155b3338236SStefano Zampini       ierr = MatMultTranspose(lA,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
215616909a7fSStefano Zampini     } else {
215716909a7fSStefano Zampini       ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N);CHKERRQ(ierr);
2158b3338236SStefano Zampini       ierr = MatMultTranspose(lA,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
215916909a7fSStefano Zampini       ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D);CHKERRQ(ierr);
216016909a7fSStefano Zampini     }
2161b097fa66SStefano Zampini   }
2162b0147a47SStefano Zampini   ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
2163c0decd05SBarry Smith   ierr = KSPCheckSolve(pcbddc->ksp_D,pc,pcis->vec4_D);CHKERRQ(ierr);
21648ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
2165b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2166b097fa66SStefano Zampini       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
2167b097fa66SStefano Zampini     } else {
2168b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
2169b097fa66SStefano Zampini     }
217050efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
217150efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2172b097fa66SStefano Zampini   } else {
2173b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2174b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
2175b097fa66SStefano Zampini     } else {
2176b097fa66SStefano Zampini       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
2177b097fa66SStefano Zampini     }
2178b097fa66SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2179b097fa66SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2180b097fa66SStefano Zampini   }
218127b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
2182537c1cdfSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
2183537c1cdfSStefano Zampini   }
21841dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2185f913dca9SStefano Zampini     pcbddc->work_change = r;
21861dd7afcfSStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
21871dd7afcfSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
21881dd7afcfSStefano Zampini   }
218950efa1b5SStefano Zampini   PetscFunctionReturn(0);
219050efa1b5SStefano Zampini }
2191674ae819SStefano Zampini 
21929326c5c6Sstefano_zampini PetscErrorCode PCReset_BDDC(PC pc)
2193da1bb401SStefano Zampini {
2194da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
21959326c5c6Sstefano_zampini   PC_IS          *pcis = (PC_IS*)pc->data;
21969326c5c6Sstefano_zampini   KSP            kspD,kspR,kspC;
2197da1bb401SStefano Zampini   PetscErrorCode ierr;
2198da1bb401SStefano Zampini 
2199da1bb401SStefano Zampini   PetscFunctionBegin;
2200674ae819SStefano Zampini   /* free BDDC custom data  */
2201674ae819SStefano Zampini   ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr);
2202674ae819SStefano Zampini   /* destroy objects related to topography */
2203674ae819SStefano Zampini   ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
220434a97f8cSStefano Zampini   /* destroy objects for scaling operator */
2205674ae819SStefano Zampini   ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
2206674ae819SStefano Zampini   /* free solvers stuff */
2207674ae819SStefano Zampini   ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
220862a6ff1dSStefano Zampini   /* free global vectors needed in presolve */
220962a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr);
221062a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr);
22111dd7afcfSStefano Zampini   /* free data created by PCIS */
22121dd7afcfSStefano Zampini   ierr = PCISDestroy(pc);CHKERRQ(ierr);
22139326c5c6Sstefano_zampini 
22149326c5c6Sstefano_zampini   /* restore defaults */
22159326c5c6Sstefano_zampini   kspD = pcbddc->ksp_D;
22169326c5c6Sstefano_zampini   kspR = pcbddc->ksp_R;
22179326c5c6Sstefano_zampini   kspC = pcbddc->coarse_ksp;
22189326c5c6Sstefano_zampini   ierr = PetscMemzero(pc->data,sizeof(*pcbddc));CHKERRQ(ierr);
22199326c5c6Sstefano_zampini   pcis->n_neigh                     = -1;
22209326c5c6Sstefano_zampini   pcis->scaling_factor              = 1.0;
22219326c5c6Sstefano_zampini   pcis->reusesubmatrices            = PETSC_TRUE;
22229326c5c6Sstefano_zampini   pcbddc->use_local_adj             = PETSC_TRUE;
22239326c5c6Sstefano_zampini   pcbddc->use_vertices              = PETSC_TRUE;
22249326c5c6Sstefano_zampini   pcbddc->use_edges                 = PETSC_TRUE;
22259326c5c6Sstefano_zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
22269326c5c6Sstefano_zampini   pcbddc->vertex_size               = 1;
22279326c5c6Sstefano_zampini   pcbddc->recompute_topography      = PETSC_TRUE;
22289326c5c6Sstefano_zampini   pcbddc->coarse_size               = -1;
22299326c5c6Sstefano_zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
22309326c5c6Sstefano_zampini   pcbddc->coarsening_ratio          = 8;
22319326c5c6Sstefano_zampini   pcbddc->coarse_eqs_per_proc       = 1;
22329326c5c6Sstefano_zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
22339326c5c6Sstefano_zampini   pcbddc->nedfield                  = -1;
22349326c5c6Sstefano_zampini   pcbddc->nedglobal                 = PETSC_TRUE;
22359326c5c6Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
22369326c5c6Sstefano_zampini   pcbddc->sub_schurs_layers         = -1;
22379326c5c6Sstefano_zampini   pcbddc->ksp_D                     = kspD;
22389326c5c6Sstefano_zampini   pcbddc->ksp_R                     = kspR;
22399326c5c6Sstefano_zampini   pcbddc->coarse_ksp                = kspC;
22409326c5c6Sstefano_zampini   PetscFunctionReturn(0);
22419326c5c6Sstefano_zampini }
22429326c5c6Sstefano_zampini 
22439326c5c6Sstefano_zampini PetscErrorCode PCDestroy_BDDC(PC pc)
22449326c5c6Sstefano_zampini {
22459326c5c6Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
22469326c5c6Sstefano_zampini   PetscErrorCode ierr;
22479326c5c6Sstefano_zampini 
22489326c5c6Sstefano_zampini   PetscFunctionBegin;
22499326c5c6Sstefano_zampini   ierr = PCReset_BDDC(pc);CHKERRQ(ierr);
22509326c5c6Sstefano_zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
22519326c5c6Sstefano_zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
22529326c5c6Sstefano_zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
2253a13144ffSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",NULL);CHKERRQ(ierr);
2254a198735bSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",NULL);CHKERRQ(ierr);
2255906d46d4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",NULL);CHKERRQ(ierr);
2256674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr);
225730368db7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",NULL);CHKERRQ(ierr);
2258bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr);
22592b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL);CHKERRQ(ierr);
2260b8ffe317SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL);CHKERRQ(ierr);
22612b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL);CHKERRQ(ierr);
2262bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
226382ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
2264bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
226582ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
2266bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
226782ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
2268bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
2269785d1243SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
2270bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr);
227163602bcaSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",NULL);CHKERRQ(ierr);
2272bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr);
2273bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr);
2274bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr);
2275bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr);
2276a06fd7f2SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",NULL);CHKERRQ(ierr);
2277ab8c8b98SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",NULL);CHKERRQ(ierr);
2278674ae819SStefano Zampini   ierr = PetscFree(pc->data);CHKERRQ(ierr);
2279da1bb401SStefano Zampini   PetscFunctionReturn(0);
2280da1bb401SStefano Zampini }
22811e6b0712SBarry Smith 
2282ab8c8b98SStefano Zampini static PetscErrorCode PCSetCoordinates_BDDC(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
2283ab8c8b98SStefano Zampini {
2284ab8c8b98SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2285ab8c8b98SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
2286ab8c8b98SStefano Zampini   PetscErrorCode ierr;
2287ab8c8b98SStefano Zampini 
2288ab8c8b98SStefano Zampini   PetscFunctionBegin;
2289ab8c8b98SStefano Zampini   ierr = PetscFree(mat_graph->coords);CHKERRQ(ierr);
2290ab8c8b98SStefano Zampini   ierr = PetscMalloc1(nloc*dim,&mat_graph->coords);CHKERRQ(ierr);
2291ab8c8b98SStefano Zampini   ierr = PetscMemcpy(mat_graph->coords,coords,nloc*dim*sizeof(PetscReal));CHKERRQ(ierr);
2292ab8c8b98SStefano Zampini   mat_graph->cnloc = nloc;
2293ab8c8b98SStefano Zampini   mat_graph->cdim  = dim;
2294ab8c8b98SStefano Zampini   mat_graph->cloc  = PETSC_FALSE;
2295*4f819b78SStefano Zampini   /* flg setup */
2296*4f819b78SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
2297*4f819b78SStefano Zampini   pcbddc->corner_selected = PETSC_FALSE;
2298ab8c8b98SStefano Zampini   PetscFunctionReturn(0);
2299ab8c8b98SStefano Zampini }
2300ab8c8b98SStefano Zampini 
2301a06fd7f2SStefano Zampini static PetscErrorCode PCPreSolveChangeRHS_BDDC(PC pc, PetscBool* change)
2302a06fd7f2SStefano Zampini {
2303a06fd7f2SStefano Zampini   PetscFunctionBegin;
2304a06fd7f2SStefano Zampini   *change = PETSC_TRUE;
2305a06fd7f2SStefano Zampini   PetscFunctionReturn(0);
2306a06fd7f2SStefano Zampini }
2307a06fd7f2SStefano Zampini 
23083425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
23093425bc38SStefano Zampini {
2310674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
2311266e20e9SStefano Zampini   Vec            work;
23123425bc38SStefano Zampini   PC_IS*         pcis;
23133425bc38SStefano Zampini   PC_BDDC*       pcbddc;
23143425bc38SStefano Zampini   PetscErrorCode ierr;
23150c7d97c5SJed Brown 
23163425bc38SStefano Zampini   PetscFunctionBegin;
23173425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
23183425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
23193425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
23203425bc38SStefano Zampini 
2321229984c5Sstefano_zampini   ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr);
2322229984c5Sstefano_zampini   /* copy rhs since we may change it during PCPreSolve_BDDC */
2323229984c5Sstefano_zampini   if (!pcbddc->original_rhs) {
2324229984c5Sstefano_zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
2325229984c5Sstefano_zampini   }
23266cc1294bSstefano_zampini   if (mat_ctx->rhs_flip) {
23276cc1294bSstefano_zampini     ierr = VecPointwiseMult(pcbddc->original_rhs,standard_rhs,mat_ctx->rhs_flip);CHKERRQ(ierr);
23286cc1294bSstefano_zampini   } else {
2329229984c5Sstefano_zampini     ierr = VecCopy(standard_rhs,pcbddc->original_rhs);CHKERRQ(ierr);
23306cc1294bSstefano_zampini   }
2331af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
2332229984c5Sstefano_zampini     /* interface pressure rhs */
2333022d8d2bSstefano_zampini     ierr = VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2334022d8d2bSstefano_zampini     ierr = VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2335229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2336229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
23376cc1294bSstefano_zampini     if (!mat_ctx->rhs_flip) {
2338229984c5Sstefano_zampini       ierr = VecScale(fetidp_flux_rhs,-1.);CHKERRQ(ierr);
2339229984c5Sstefano_zampini     }
23406cc1294bSstefano_zampini   }
2341c08af4c6SStefano Zampini   /*
2342c08af4c6SStefano Zampini      change of basis for physical rhs if needed
2343c08af4c6SStefano Zampini      It also changes the rhs in case of dirichlet boundaries
2344c08af4c6SStefano Zampini   */
23453738a8e6SStefano Zampini   ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,pcbddc->original_rhs,NULL);CHKERRQ(ierr);
2346fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
23473738a8e6SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcbddc->original_rhs,pcbddc->work_change);CHKERRQ(ierr);
23483738a8e6SStefano Zampini     work = pcbddc->work_change;
2349fc17d649SStefano Zampini    } else {
23503738a8e6SStefano Zampini     work = pcbddc->original_rhs;
2351fc17d649SStefano Zampini   }
23523425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
2353266e20e9SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2354266e20e9SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2355fb223d50SStefano Zampini   /* scale rhs since it should be unassembled */
2356fb223d50SStefano Zampini   /* TODO use counter scaling? (also below) */
2357266e20e9SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2358266e20e9SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2359674ae819SStefano Zampini   /* Apply partition of unity */
23603425bc38SStefano Zampini   ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
2361266e20e9SStefano Zampini   /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
23628eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
23633425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
23643425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
2365c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
23663425bc38SStefano Zampini     ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr);
23673425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr);
2368266e20e9SStefano Zampini     ierr = VecSet(work,0.0);CHKERRQ(ierr);
2369266e20e9SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2370266e20e9SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2371266e20e9SStefano Zampini     /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
2372266e20e9SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2373266e20e9SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
23743425bc38SStefano Zampini     ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
23753425bc38SStefano Zampini   }
23763425bc38SStefano Zampini   /* BDDC rhs */
23773425bc38SStefano Zampini   ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr);
23788eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
23793425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
23803425bc38SStefano Zampini   }
23813425bc38SStefano Zampini   /* apply BDDC */
2382229984c5Sstefano_zampini   ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
2383dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
2384266e20e9SStefano Zampini   ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
2385229984c5Sstefano_zampini 
23863425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
23873425bc38SStefano Zampini   ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr);
23883425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
23893425bc38SStefano Zampini   ierr = VecScatterEnd(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2390229984c5Sstefano_zampini   /* Add contribution to interface pressures */
2391229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
2392229984c5Sstefano_zampini     ierr = MatMult(mat_ctx->B_BB,pcis->vec1_B,mat_ctx->vP);CHKERRQ(ierr);
2393229984c5Sstefano_zampini     if (pcbddc->switch_static) {
2394229984c5Sstefano_zampini       ierr = MatMultAdd(mat_ctx->B_BI,pcis->vec1_D,mat_ctx->vP,mat_ctx->vP);CHKERRQ(ierr);
2395229984c5Sstefano_zampini     }
2396229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2397229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2398229984c5Sstefano_zampini   }
23993425bc38SStefano Zampini   PetscFunctionReturn(0);
24003425bc38SStefano Zampini }
24011e6b0712SBarry Smith 
24023425bc38SStefano Zampini /*@
24030f202f7eSStefano Zampini  PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side
24043425bc38SStefano Zampini 
24053425bc38SStefano Zampini    Collective
24063425bc38SStefano Zampini 
24073425bc38SStefano Zampini    Input Parameters:
24080f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix object obtained by a call to PCBDDCCreateFETIDPOperators
24090f202f7eSStefano Zampini -  standard_rhs    - the right-hand side of the original linear system
24103425bc38SStefano Zampini 
24113425bc38SStefano Zampini    Output Parameters:
24120f202f7eSStefano Zampini .  fetidp_flux_rhs - the right-hand side for the FETI-DP linear system
24133425bc38SStefano Zampini 
24143425bc38SStefano Zampini    Level: developer
24153425bc38SStefano Zampini 
24163425bc38SStefano Zampini    Notes:
24173425bc38SStefano Zampini 
24180f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetSolution
24193425bc38SStefano Zampini @*/
24203425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
24213425bc38SStefano Zampini {
2422674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
24233425bc38SStefano Zampini   PetscErrorCode ierr;
24243425bc38SStefano Zampini 
24253425bc38SStefano Zampini   PetscFunctionBegin;
2426266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1);
2427266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_rhs,VEC_CLASSID,2);
2428266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_rhs,VEC_CLASSID,3);
24293425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
2430163d334eSBarry Smith   ierr = PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr);
24313425bc38SStefano Zampini   PetscFunctionReturn(0);
24323425bc38SStefano Zampini }
24331e6b0712SBarry Smith 
24343425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
24353425bc38SStefano Zampini {
2436674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
24373425bc38SStefano Zampini   PC_IS*         pcis;
24383425bc38SStefano Zampini   PC_BDDC*       pcbddc;
24393425bc38SStefano Zampini   PetscErrorCode ierr;
2440229984c5Sstefano_zampini   Vec            work;
24413425bc38SStefano Zampini 
24423425bc38SStefano Zampini   PetscFunctionBegin;
24433425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
24443425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
24453425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
24463425bc38SStefano Zampini 
24473425bc38SStefano Zampini   /* apply B_delta^T */
2448af140850Sstefano_zampini   ierr = VecSet(pcis->vec1_B,0.);CHKERRQ(ierr);
24493425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
24503425bc38SStefano Zampini   ierr = VecScatterEnd(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
24513425bc38SStefano Zampini   ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
2452229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
2453229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2454229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2455229984c5Sstefano_zampini     ierr = MatMultAdd(mat_ctx->Bt_BB,mat_ctx->vP,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
2456229984c5Sstefano_zampini   }
2457229984c5Sstefano_zampini 
24583425bc38SStefano Zampini   /* compute rhs for BDDC application */
24593425bc38SStefano Zampini   ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr);
24608eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
24613425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
2462229984c5Sstefano_zampini     if (mat_ctx->l2g_p) {
2463229984c5Sstefano_zampini       ierr = VecScale(mat_ctx->vP,-1.);CHKERRQ(ierr);
2464229984c5Sstefano_zampini       ierr = MatMultAdd(mat_ctx->Bt_BI,mat_ctx->vP,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr);
24653425bc38SStefano Zampini     }
2466229984c5Sstefano_zampini   }
2467229984c5Sstefano_zampini 
24683425bc38SStefano Zampini   /* apply BDDC */
2469229984c5Sstefano_zampini   ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
2470dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
2471229984c5Sstefano_zampini 
2472229984c5Sstefano_zampini   /* put values into global vector */
2473af140850Sstefano_zampini   if (pcbddc->ChangeOfBasisMatrix) work = pcbddc->work_change;
2474af140850Sstefano_zampini   else work = standard_sol;
2475229984c5Sstefano_zampini   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2476229984c5Sstefano_zampini   ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
24778eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
24783425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
24793425bc38SStefano Zampini     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr);
248000f6b531SStefano Zampini     ierr = VecAYPX(pcis->vec1_D,-1.0,mat_ctx->temp_solution_D);CHKERRQ(ierr);
248100f6b531SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr);
2482c0decd05SBarry Smith     /* Cannot propagate up error in KSPSolve() because there is no access to the PC */
24833425bc38SStefano Zampini   }
2484229984c5Sstefano_zampini 
2485229984c5Sstefano_zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2486229984c5Sstefano_zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2487266e20e9SStefano Zampini   /* add p0 solution to final solution */
2488229984c5Sstefano_zampini   ierr = PCBDDCBenignGetOrSetP0(mat_ctx->pc,work,PETSC_FALSE);CHKERRQ(ierr);
2489fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2490af140850Sstefano_zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,work,standard_sol);CHKERRQ(ierr);
2491fc17d649SStefano Zampini   }
2492af140850Sstefano_zampini   ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr);
2493af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
2494229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2495229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2496229984c5Sstefano_zampini   }
24973425bc38SStefano Zampini   PetscFunctionReturn(0);
24983425bc38SStefano Zampini }
24991e6b0712SBarry Smith 
25005a1e936bSStefano Zampini static PetscErrorCode PCView_BDDCIPC(PC pc, PetscViewer viewer)
25015a1e936bSStefano Zampini {
25025a1e936bSStefano Zampini   PetscErrorCode ierr;
25035a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25045a1e936bSStefano Zampini   PetscBool      isascii;
25055a1e936bSStefano Zampini 
25065a1e936bSStefano Zampini   PetscFunctionBegin;
25075a1e936bSStefano Zampini   ierr = PCShellGetContext(pc,(void **)&bddcipc_ctx);CHKERRQ(ierr);
25085a1e936bSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
25095a1e936bSStefano Zampini   if (isascii) {
25105a1e936bSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"BDDC interface preconditioner\n");CHKERRQ(ierr);
25115a1e936bSStefano Zampini   }
25125a1e936bSStefano Zampini   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
25135a1e936bSStefano Zampini   ierr = PCView(bddcipc_ctx->bddc,viewer);CHKERRQ(ierr);
25145a1e936bSStefano Zampini   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
25155a1e936bSStefano Zampini   PetscFunctionReturn(0);
25165a1e936bSStefano Zampini }
25175a1e936bSStefano Zampini 
25185a1e936bSStefano Zampini static PetscErrorCode PCSetUp_BDDCIPC(PC pc)
25195a1e936bSStefano Zampini {
25205a1e936bSStefano Zampini   PetscErrorCode ierr;
25215a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25225a1e936bSStefano Zampini   PetscBool      isbddc;
25235a1e936bSStefano Zampini   Vec            vv;
25245a1e936bSStefano Zampini   IS             is;
25255a1e936bSStefano Zampini   PC_IS          *pcis;
25265a1e936bSStefano Zampini 
25275a1e936bSStefano Zampini   PetscFunctionBegin;
25285a1e936bSStefano Zampini   ierr = PCShellGetContext(pc,(void **)&bddcipc_ctx);CHKERRQ(ierr);
25295a1e936bSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)bddcipc_ctx->bddc,PCBDDC,&isbddc);CHKERRQ(ierr);
25305a1e936bSStefano Zampini   if (!isbddc) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid type %s. Must be of type bddc",((PetscObject)bddcipc_ctx->bddc)->type_name);
25315a1e936bSStefano Zampini   ierr = PCSetUp(bddcipc_ctx->bddc);CHKERRQ(ierr);
25325a1e936bSStefano Zampini 
25335a1e936bSStefano Zampini   /* create interface scatter */
25345a1e936bSStefano Zampini   pcis = (PC_IS*)(bddcipc_ctx->bddc->data);
25355a1e936bSStefano Zampini   ierr = VecScatterDestroy(&bddcipc_ctx->g2l);CHKERRQ(ierr);
25365a1e936bSStefano Zampini   ierr = MatCreateVecs(pc->pmat,&vv,NULL);CHKERRQ(ierr);
25375a1e936bSStefano Zampini   ierr = ISRenumber(pcis->is_B_global,NULL,NULL,&is);CHKERRQ(ierr);
253835928de7SBarry Smith   ierr = VecScatterCreateWithData(vv,is,pcis->vec1_B,NULL,&bddcipc_ctx->g2l);CHKERRQ(ierr);
25395a1e936bSStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
25405a1e936bSStefano Zampini   ierr = VecDestroy(&vv);CHKERRQ(ierr);
25415a1e936bSStefano Zampini   PetscFunctionReturn(0);
25425a1e936bSStefano Zampini }
25435a1e936bSStefano Zampini 
25445a1e936bSStefano Zampini static PetscErrorCode PCApply_BDDCIPC(PC pc, Vec r, Vec x)
25455a1e936bSStefano Zampini {
25465a1e936bSStefano Zampini   PetscErrorCode ierr;
25475a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25485a1e936bSStefano Zampini   PC_IS          *pcis;
25495a1e936bSStefano Zampini   VecScatter     tmps;
25505a1e936bSStefano Zampini 
25515a1e936bSStefano Zampini   PetscFunctionBegin;
25525a1e936bSStefano Zampini   ierr = PCShellGetContext(pc,(void **)&bddcipc_ctx);CHKERRQ(ierr);
25535a1e936bSStefano Zampini   pcis = (PC_IS*)(bddcipc_ctx->bddc->data);
25545a1e936bSStefano Zampini   tmps = pcis->global_to_B;
25555a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
25565a1e936bSStefano Zampini   ierr = PCBDDCScalingRestriction(bddcipc_ctx->bddc,r,pcis->vec1_B);CHKERRQ(ierr);
25575a1e936bSStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc,PETSC_FALSE);CHKERRQ(ierr);
25585a1e936bSStefano Zampini   ierr = PCBDDCScalingExtension(bddcipc_ctx->bddc,pcis->vec1_B,x);CHKERRQ(ierr);
25595a1e936bSStefano Zampini   pcis->global_to_B = tmps;
25605a1e936bSStefano Zampini   PetscFunctionReturn(0);
25615a1e936bSStefano Zampini }
25625a1e936bSStefano Zampini 
25635a1e936bSStefano Zampini static PetscErrorCode PCApplyTranspose_BDDCIPC(PC pc, Vec r, Vec x)
25645a1e936bSStefano Zampini {
25655a1e936bSStefano Zampini   PetscErrorCode ierr;
25665a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25675a1e936bSStefano Zampini   PC_IS          *pcis;
25685a1e936bSStefano Zampini   VecScatter     tmps;
25695a1e936bSStefano Zampini 
25705a1e936bSStefano Zampini   PetscFunctionBegin;
25715a1e936bSStefano Zampini   ierr = PCShellGetContext(pc,(void **)&bddcipc_ctx);CHKERRQ(ierr);
25725a1e936bSStefano Zampini   pcis = (PC_IS*)(bddcipc_ctx->bddc->data);
25735a1e936bSStefano Zampini   tmps = pcis->global_to_B;
25745a1e936bSStefano Zampini   pcis->global_to_B = bddcipc_ctx->g2l;
25755a1e936bSStefano Zampini   ierr = PCBDDCScalingRestriction(bddcipc_ctx->bddc,r,pcis->vec1_B);CHKERRQ(ierr);
25765a1e936bSStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(bddcipc_ctx->bddc,PETSC_TRUE);CHKERRQ(ierr);
25775a1e936bSStefano Zampini   ierr = PCBDDCScalingExtension(bddcipc_ctx->bddc,pcis->vec1_B,x);CHKERRQ(ierr);
25785a1e936bSStefano Zampini   pcis->global_to_B = tmps;
25795a1e936bSStefano Zampini   PetscFunctionReturn(0);
25805a1e936bSStefano Zampini }
25815a1e936bSStefano Zampini 
25825a1e936bSStefano Zampini static PetscErrorCode PCDestroy_BDDCIPC(PC pc)
25835a1e936bSStefano Zampini {
25845a1e936bSStefano Zampini   PetscErrorCode ierr;
25855a1e936bSStefano Zampini   BDDCIPC_ctx    bddcipc_ctx;
25865a1e936bSStefano Zampini 
25875a1e936bSStefano Zampini   PetscFunctionBegin;
25885a1e936bSStefano Zampini   ierr = PCShellGetContext(pc,(void **)&bddcipc_ctx);CHKERRQ(ierr);
25895a1e936bSStefano Zampini   ierr = PCDestroy(&bddcipc_ctx->bddc);CHKERRQ(ierr);
25905a1e936bSStefano Zampini   ierr = VecScatterDestroy(&bddcipc_ctx->g2l);CHKERRQ(ierr);
25915a1e936bSStefano Zampini   ierr = PetscFree(bddcipc_ctx);CHKERRQ(ierr);
25925a1e936bSStefano Zampini   PetscFunctionReturn(0);
25935a1e936bSStefano Zampini }
25945a1e936bSStefano Zampini 
25953425bc38SStefano Zampini /*@
25960f202f7eSStefano Zampini  PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system
25973425bc38SStefano Zampini 
25983425bc38SStefano Zampini    Collective
25993425bc38SStefano Zampini 
26003425bc38SStefano Zampini    Input Parameters:
26010f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators
26020f202f7eSStefano Zampini -  fetidp_flux_sol - the solution of the FETI-DP linear system
26033425bc38SStefano Zampini 
26043425bc38SStefano Zampini    Output Parameters:
26050f202f7eSStefano Zampini .  standard_sol    - the solution defined on the physical domain
26063425bc38SStefano Zampini 
26073425bc38SStefano Zampini    Level: developer
26083425bc38SStefano Zampini 
26093425bc38SStefano Zampini    Notes:
26103425bc38SStefano Zampini 
26110f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetRHS
26123425bc38SStefano Zampini @*/
26133425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
26143425bc38SStefano Zampini {
2615674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
26163425bc38SStefano Zampini   PetscErrorCode ierr;
26173425bc38SStefano Zampini 
26183425bc38SStefano Zampini   PetscFunctionBegin;
2619266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1);
2620266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_sol,VEC_CLASSID,2);
2621266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_sol,VEC_CLASSID,3);
26223425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
2623163d334eSBarry Smith   ierr = PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr);
26243425bc38SStefano Zampini   PetscFunctionReturn(0);
26253425bc38SStefano Zampini }
26261e6b0712SBarry Smith 
2627547c9a8eSstefano_zampini static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, PetscBool fully_redundant, const char* prefix, Mat *fetidp_mat, PC *fetidp_pc)
26283425bc38SStefano Zampini {
2629674ae819SStefano Zampini 
2630674ae819SStefano Zampini   FETIDPMat_ctx  fetidpmat_ctx;
26313425bc38SStefano Zampini   Mat            newmat;
2632674ae819SStefano Zampini   FETIDPPC_ctx   fetidppc_ctx;
26333425bc38SStefano Zampini   PC             newpc;
2634ce94432eSBarry Smith   MPI_Comm       comm;
26353425bc38SStefano Zampini   PetscErrorCode ierr;
26363425bc38SStefano Zampini 
26373425bc38SStefano Zampini   PetscFunctionBegin;
2638ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
263915579a77SStefano Zampini   /* FETI-DP matrix */
26403425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr);
26411720468bSStefano Zampini   fetidpmat_ctx->fully_redundant = fully_redundant;
26423425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr);
2643a5bb87b3Sstefano_zampini   ierr = MatCreateShell(comm,fetidpmat_ctx->n,fetidpmat_ctx->n,fetidpmat_ctx->N,fetidpmat_ctx->N,fetidpmat_ctx,&newmat);CHKERRQ(ierr);
264415579a77SStefano Zampini   ierr = PetscObjectSetName((PetscObject)newmat,!fetidpmat_ctx->l2g_lambda_only ? "F" : "G");CHKERRQ(ierr);
26453425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr);
2646edf7251bSStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT_TRANSPOSE,(void (*)(void))FETIDPMatMultTranspose);CHKERRQ(ierr);
26473425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr);
264815579a77SStefano Zampini   /* propagate MatOptions */
264915579a77SStefano Zampini   {
265015579a77SStefano Zampini     PC_BDDC   *pcbddc = (PC_BDDC*)fetidpmat_ctx->pc->data;
265115579a77SStefano Zampini     PetscBool issym;
265215579a77SStefano Zampini 
265315579a77SStefano Zampini     ierr = MatGetOption(pc->mat,MAT_SYMMETRIC,&issym);CHKERRQ(ierr);
265415579a77SStefano Zampini     if (issym || pcbddc->symmetric_primal) {
265515579a77SStefano Zampini       ierr = MatSetOption(newmat,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
265615579a77SStefano Zampini     }
265715579a77SStefano Zampini   }
2658547c9a8eSstefano_zampini   ierr = MatSetOptionsPrefix(newmat,prefix);CHKERRQ(ierr);
2659547c9a8eSstefano_zampini   ierr = MatAppendOptionsPrefix(newmat,"fetidp_");CHKERRQ(ierr);
26603425bc38SStefano Zampini   ierr = MatSetUp(newmat);CHKERRQ(ierr);
266115579a77SStefano Zampini   /* FETI-DP preconditioner */
26623425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr);
26633425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr);
26643425bc38SStefano Zampini   ierr = PCCreate(comm,&newpc);CHKERRQ(ierr);
2665e1214c54Sstefano_zampini   ierr = PCSetOperators(newpc,newmat,newmat);CHKERRQ(ierr);
2666e1214c54Sstefano_zampini   ierr = PCSetOptionsPrefix(newpc,prefix);CHKERRQ(ierr);
2667e1214c54Sstefano_zampini   ierr = PCAppendOptionsPrefix(newpc,"fetidp_");CHKERRQ(ierr);
2668399ffe99SStefano Zampini   ierr = PCSetErrorIfFailure(newpc,pc->erroriffailure);CHKERRQ(ierr);
266915579a77SStefano Zampini   if (!fetidpmat_ctx->l2g_lambda_only) { /* standard FETI-DP */
26703425bc38SStefano Zampini     ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
267115579a77SStefano Zampini     ierr = PCShellSetName(newpc,"FETI-DP multipliers");CHKERRQ(ierr);
26723425bc38SStefano Zampini     ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr);
26733425bc38SStefano Zampini     ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr);
2674edf7251bSStefano Zampini     ierr = PCShellSetApplyTranspose(newpc,FETIDPPCApplyTranspose);CHKERRQ(ierr);
2675c45b8d2dSstefano_zampini     ierr = PCShellSetView(newpc,FETIDPPCView);CHKERRQ(ierr);
26763425bc38SStefano Zampini     ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
26775a1e936bSStefano Zampini   } else { /* saddle-point FETI-DP */
26785a1e936bSStefano Zampini     Mat       M;
26795a1e936bSStefano Zampini     PetscInt  psize;
26805a1e936bSStefano Zampini     PetscBool fake = PETSC_FALSE, isfieldsplit;
2681e1214c54Sstefano_zampini 
268215579a77SStefano Zampini     ierr = ISViewFromOptions(fetidpmat_ctx->lagrange,NULL,"-lag_view");CHKERRQ(ierr);
268315579a77SStefano Zampini     ierr = ISViewFromOptions(fetidpmat_ctx->pressure,NULL,"-press_view");CHKERRQ(ierr);
2684e1214c54Sstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_PPmat",(PetscObject*)&M);CHKERRQ(ierr);
2685e1214c54Sstefano_zampini     ierr = PCSetType(newpc,PCFIELDSPLIT);CHKERRQ(ierr);
2686e1214c54Sstefano_zampini     ierr = PCFieldSplitSetIS(newpc,"lag",fetidpmat_ctx->lagrange);CHKERRQ(ierr);
2687e1214c54Sstefano_zampini     ierr = PCFieldSplitSetIS(newpc,"p",fetidpmat_ctx->pressure);CHKERRQ(ierr);
2688e1214c54Sstefano_zampini     ierr = PCFieldSplitSetType(newpc,PC_COMPOSITE_SCHUR);CHKERRQ(ierr);
268940c75d76SStefano Zampini     ierr = PCFieldSplitSetSchurFactType(newpc,PC_FIELDSPLIT_SCHUR_FACT_DIAG);CHKERRQ(ierr);
26905a1e936bSStefano Zampini     ierr = ISGetSize(fetidpmat_ctx->pressure,&psize);CHKERRQ(ierr);
26915a1e936bSStefano Zampini     if (psize != M->rmap->N) {
26925a1e936bSStefano Zampini       Mat      M2;
26935a1e936bSStefano Zampini       PetscInt lpsize;
26945a1e936bSStefano Zampini 
26955a1e936bSStefano Zampini       fake = PETSC_TRUE;
26965a1e936bSStefano Zampini       ierr = ISGetLocalSize(fetidpmat_ctx->pressure,&lpsize);CHKERRQ(ierr);
26975a1e936bSStefano Zampini       ierr = MatCreate(comm,&M2);CHKERRQ(ierr);
26985a1e936bSStefano Zampini       ierr = MatSetType(M2,MATAIJ);CHKERRQ(ierr);
26995a1e936bSStefano Zampini       ierr = MatSetSizes(M2,lpsize,lpsize,psize,psize);CHKERRQ(ierr);
27005a1e936bSStefano Zampini       ierr = MatSetUp(M2);CHKERRQ(ierr);
27015a1e936bSStefano Zampini       ierr = MatAssemblyBegin(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27025a1e936bSStefano Zampini       ierr = MatAssemblyEnd(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27035a1e936bSStefano Zampini       ierr = PCFieldSplitSetSchurPre(newpc,PC_FIELDSPLIT_SCHUR_PRE_USER,M2);CHKERRQ(ierr);
27045a1e936bSStefano Zampini       ierr = MatDestroy(&M2);CHKERRQ(ierr);
27055a1e936bSStefano Zampini     } else {
2706e1214c54Sstefano_zampini       ierr = PCFieldSplitSetSchurPre(newpc,PC_FIELDSPLIT_SCHUR_PRE_USER,M);CHKERRQ(ierr);
27075a1e936bSStefano Zampini     }
2708c096484dSStefano Zampini     ierr = PCFieldSplitSetSchurScale(newpc,1.0);CHKERRQ(ierr);
270915579a77SStefano Zampini 
271015579a77SStefano Zampini     /* we need to setfromoptions and setup here to access the blocks */
2711e1214c54Sstefano_zampini     ierr = PCSetFromOptions(newpc);CHKERRQ(ierr);
2712e1214c54Sstefano_zampini     ierr = PCSetUp(newpc);CHKERRQ(ierr);
2713e1214c54Sstefano_zampini 
27145a1e936bSStefano Zampini     /* user may have changed the type (e.g. -fetidp_pc_type none) */
27155a1e936bSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)newpc,PCFIELDSPLIT,&isfieldsplit);CHKERRQ(ierr);
27165a1e936bSStefano Zampini     if (isfieldsplit) {
27175a1e936bSStefano Zampini       KSP       *ksps;
27185a1e936bSStefano Zampini       PC        ppc,lagpc;
27195a1e936bSStefano Zampini       PetscInt  nn;
2720064a4176SStefano Zampini       PetscBool ismatis,matisok = PETSC_FALSE,check = PETSC_FALSE;
27215a1e936bSStefano Zampini 
2722e1214c54Sstefano_zampini       /* set the solver for the (0,0) block */
27235a1e936bSStefano Zampini       ierr = PCFieldSplitSchurGetSubKSP(newpc,&nn,&ksps);CHKERRQ(ierr);
27245a1e936bSStefano Zampini       if (!nn) { /* not of type PC_COMPOSITE_SCHUR */
272540c75d76SStefano Zampini         ierr = PCFieldSplitGetSubKSP(newpc,&nn,&ksps);CHKERRQ(ierr);
27265a1e936bSStefano Zampini         if (!fake) { /* pass pmat to the pressure solver */
27275a1e936bSStefano Zampini           Mat F;
27285a1e936bSStefano Zampini 
27295a1e936bSStefano Zampini           ierr = KSPGetOperators(ksps[1],&F,NULL);CHKERRQ(ierr);
27305a1e936bSStefano Zampini           ierr = KSPSetOperators(ksps[1],F,M);CHKERRQ(ierr);
27315a1e936bSStefano Zampini         }
27325a1e936bSStefano Zampini       } else {
27335a1e936bSStefano Zampini         PetscBool issym;
27345a1e936bSStefano Zampini         Mat       S;
27355a1e936bSStefano Zampini 
27365a1e936bSStefano Zampini         ierr = PCFieldSplitSchurGetS(newpc,&S);CHKERRQ(ierr);
27375a1e936bSStefano Zampini 
27385a1e936bSStefano Zampini         ierr = MatGetOption(newmat,MAT_SYMMETRIC,&issym);CHKERRQ(ierr);
27395a1e936bSStefano Zampini         if (issym) {
27405a1e936bSStefano Zampini           ierr = MatSetOption(S,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
27415a1e936bSStefano Zampini         }
27425a1e936bSStefano Zampini       }
27435a1e936bSStefano Zampini       ierr = KSPGetPC(ksps[0],&lagpc);CHKERRQ(ierr);
2744e1214c54Sstefano_zampini       ierr = PCSetType(lagpc,PCSHELL);CHKERRQ(ierr);
27455a1e936bSStefano Zampini       ierr = PCShellSetName(lagpc,"FETI-DP multipliers");CHKERRQ(ierr);
2746e1214c54Sstefano_zampini       ierr = PCShellSetContext(lagpc,fetidppc_ctx);CHKERRQ(ierr);
2747e1214c54Sstefano_zampini       ierr = PCShellSetApply(lagpc,FETIDPPCApply);CHKERRQ(ierr);
2748e1214c54Sstefano_zampini       ierr = PCShellSetApplyTranspose(lagpc,FETIDPPCApplyTranspose);CHKERRQ(ierr);
2749e1214c54Sstefano_zampini       ierr = PCShellSetView(lagpc,FETIDPPCView);CHKERRQ(ierr);
2750e1214c54Sstefano_zampini       ierr = PCShellSetDestroy(lagpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
27515a1e936bSStefano Zampini 
27525a1e936bSStefano Zampini       /* Olof's idea: interface Schur complement preconditioner for the mass matrix */
27535a1e936bSStefano Zampini       ierr = KSPGetPC(ksps[1],&ppc);CHKERRQ(ierr);
27545a1e936bSStefano Zampini       if (fake) {
27555a1e936bSStefano Zampini         BDDCIPC_ctx    bddcipc_ctx;
2756ff11fd76SStefano Zampini         PetscContainer c;
27575a1e936bSStefano Zampini 
27585a1e936bSStefano Zampini         matisok = PETSC_TRUE;
27595a1e936bSStefano Zampini 
27605a1e936bSStefano Zampini         /* create inner BDDC solver */
27615a1e936bSStefano Zampini         ierr = PetscNew(&bddcipc_ctx);CHKERRQ(ierr);
27625a1e936bSStefano Zampini         ierr = PCCreate(comm,&bddcipc_ctx->bddc);CHKERRQ(ierr);
27635a1e936bSStefano Zampini         ierr = PCSetType(bddcipc_ctx->bddc,PCBDDC);CHKERRQ(ierr);
27645a1e936bSStefano Zampini         ierr = PCSetOperators(bddcipc_ctx->bddc,M,M);CHKERRQ(ierr);
2765ff11fd76SStefano Zampini         ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_pCSR",(PetscObject*)&c);CHKERRQ(ierr);
2766ff11fd76SStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)M,MATIS,&ismatis);CHKERRQ(ierr);
2767ff11fd76SStefano Zampini         if (c && ismatis) {
2768ff11fd76SStefano Zampini           Mat      lM;
2769ff11fd76SStefano Zampini           PetscInt *csr,n;
2770ff11fd76SStefano Zampini 
2771ff11fd76SStefano Zampini           ierr = MatISGetLocalMat(M,&lM);CHKERRQ(ierr);
2772ff11fd76SStefano Zampini           ierr = MatGetSize(lM,&n,NULL);CHKERRQ(ierr);
2773ff11fd76SStefano Zampini           ierr = PetscContainerGetPointer(c,(void**)&csr);CHKERRQ(ierr);
2774ff11fd76SStefano Zampini           ierr = PCBDDCSetLocalAdjacencyGraph(bddcipc_ctx->bddc,n,csr,csr + (n + 1),PETSC_COPY_VALUES);CHKERRQ(ierr);
2775ff11fd76SStefano Zampini           ierr = MatISRestoreLocalMat(M,&lM);CHKERRQ(ierr);
2776ff11fd76SStefano Zampini         }
27775a1e936bSStefano Zampini         ierr = PCSetOptionsPrefix(bddcipc_ctx->bddc,((PetscObject)ksps[1])->prefix);CHKERRQ(ierr);
27785a1e936bSStefano Zampini         ierr = PCSetErrorIfFailure(bddcipc_ctx->bddc,pc->erroriffailure);CHKERRQ(ierr);
27795a1e936bSStefano Zampini         ierr = PCSetFromOptions(bddcipc_ctx->bddc);CHKERRQ(ierr);
27805a1e936bSStefano Zampini 
27815a1e936bSStefano Zampini         /* wrap the interface application */
27825a1e936bSStefano Zampini         ierr = PCSetType(ppc,PCSHELL);CHKERRQ(ierr);
27835a1e936bSStefano Zampini         ierr = PCShellSetName(ppc,"FETI-DP pressure");CHKERRQ(ierr);
27845a1e936bSStefano Zampini         ierr = PCShellSetContext(ppc,bddcipc_ctx);CHKERRQ(ierr);
27855a1e936bSStefano Zampini         ierr = PCShellSetSetUp(ppc,PCSetUp_BDDCIPC);CHKERRQ(ierr);
27865a1e936bSStefano Zampini         ierr = PCShellSetApply(ppc,PCApply_BDDCIPC);CHKERRQ(ierr);
27875a1e936bSStefano Zampini         ierr = PCShellSetApplyTranspose(ppc,PCApplyTranspose_BDDCIPC);CHKERRQ(ierr);
27885a1e936bSStefano Zampini         ierr = PCShellSetView(ppc,PCView_BDDCIPC);CHKERRQ(ierr);
27895a1e936bSStefano Zampini         ierr = PCShellSetDestroy(ppc,PCDestroy_BDDCIPC);CHKERRQ(ierr);
27905a1e936bSStefano Zampini       }
27915a1e936bSStefano Zampini 
27925a1e936bSStefano Zampini       /* determine if we need to assemble M to construct a preconditioner */
27935a1e936bSStefano Zampini       if (!matisok) {
27945a1e936bSStefano Zampini         ierr = PetscObjectTypeCompare((PetscObject)M,MATIS,&ismatis);CHKERRQ(ierr);
27955a1e936bSStefano Zampini         ierr = PetscObjectTypeCompareAny((PetscObject)ppc,&matisok,PCBDDC,PCJACOBI,PCNONE,PCMG,"");CHKERRQ(ierr);
27965a1e936bSStefano Zampini         if (ismatis && !matisok) {
27975a1e936bSStefano Zampini           ierr = MatConvert(M,MATAIJ,MAT_INPLACE_MATRIX,&M);CHKERRQ(ierr);
27985a1e936bSStefano Zampini         }
27995a1e936bSStefano Zampini       }
2800064a4176SStefano Zampini 
2801064a4176SStefano Zampini       /* run the subproblems to check convergence */
2802064a4176SStefano Zampini       ierr = PetscOptionsGetBool(NULL,((PetscObject)newmat)->prefix,"-check_saddlepoint",&check,NULL);CHKERRQ(ierr);
2803064a4176SStefano Zampini       if (check) {
2804064a4176SStefano Zampini         PetscInt i;
2805064a4176SStefano Zampini 
2806064a4176SStefano Zampini         for (i=0;i<nn;i++) {
2807064a4176SStefano Zampini           KSP       kspC;
2808064a4176SStefano Zampini           PC        pc;
2809064a4176SStefano Zampini           Mat       F,pF;
2810064a4176SStefano Zampini           Vec       x,y;
2811064a4176SStefano Zampini           PetscBool isschur,prec = PETSC_TRUE;
2812064a4176SStefano Zampini 
2813064a4176SStefano Zampini           ierr = KSPCreate(PetscObjectComm((PetscObject)ksps[i]),&kspC);CHKERRQ(ierr);
2814064a4176SStefano Zampini           ierr = KSPSetOptionsPrefix(kspC,((PetscObject)ksps[i])->prefix);CHKERRQ(ierr);
2815064a4176SStefano Zampini           ierr = KSPAppendOptionsPrefix(kspC,"check_");CHKERRQ(ierr);
2816064a4176SStefano Zampini           ierr = KSPGetOperators(ksps[i],&F,&pF);CHKERRQ(ierr);
2817064a4176SStefano Zampini           ierr = PetscObjectTypeCompare((PetscObject)F,MATSCHURCOMPLEMENT,&isschur);CHKERRQ(ierr);
2818064a4176SStefano Zampini           if (isschur) {
2819064a4176SStefano Zampini             KSP  kspS,kspS2;
2820064a4176SStefano Zampini             Mat  A00,pA00,A10,A01,A11;
2821064a4176SStefano Zampini             char prefix[256];
2822064a4176SStefano Zampini 
2823064a4176SStefano Zampini             ierr = MatSchurComplementGetKSP(F,&kspS);CHKERRQ(ierr);
2824064a4176SStefano Zampini             ierr = MatSchurComplementGetSubMatrices(F,&A00,&pA00,&A01,&A10,&A11);CHKERRQ(ierr);
2825064a4176SStefano Zampini             ierr = MatCreateSchurComplement(A00,pA00,A01,A10,A11,&F);CHKERRQ(ierr);
2826064a4176SStefano Zampini             ierr = MatSchurComplementGetKSP(F,&kspS2);CHKERRQ(ierr);
2827064a4176SStefano Zampini             ierr = PetscSNPrintf(prefix,sizeof(prefix),"%sschur_",((PetscObject)kspC)->prefix);CHKERRQ(ierr);
2828064a4176SStefano Zampini             ierr = KSPSetOptionsPrefix(kspS2,prefix);CHKERRQ(ierr);
2829064a4176SStefano Zampini             ierr = KSPGetPC(kspS2,&pc);CHKERRQ(ierr);
2830064a4176SStefano Zampini             ierr = PCSetType(pc,PCKSP);CHKERRQ(ierr);
2831064a4176SStefano Zampini             ierr = PCKSPSetKSP(pc,kspS);CHKERRQ(ierr);
2832064a4176SStefano Zampini             ierr = KSPSetFromOptions(kspS2);CHKERRQ(ierr);
2833064a4176SStefano Zampini             ierr = KSPGetPC(kspS2,&pc);CHKERRQ(ierr);
2834064a4176SStefano Zampini             ierr = PCSetUseAmat(pc,PETSC_TRUE);CHKERRQ(ierr);
2835064a4176SStefano Zampini           } else {
2836064a4176SStefano Zampini             ierr = PetscObjectReference((PetscObject)F);CHKERRQ(ierr);
2837064a4176SStefano Zampini           }
2838064a4176SStefano Zampini           ierr = KSPSetFromOptions(kspC);CHKERRQ(ierr);
2839064a4176SStefano Zampini           ierr = PetscOptionsGetBool(NULL,((PetscObject)kspC)->prefix,"-preconditioned",&prec,NULL);CHKERRQ(ierr);
2840064a4176SStefano Zampini           if (prec)  {
2841064a4176SStefano Zampini             ierr = KSPGetPC(ksps[i],&pc);CHKERRQ(ierr);
2842064a4176SStefano Zampini             ierr = KSPSetPC(kspC,pc);CHKERRQ(ierr);
2843064a4176SStefano Zampini           }
2844064a4176SStefano Zampini           ierr = KSPSetOperators(kspC,F,pF);CHKERRQ(ierr);
2845064a4176SStefano Zampini           ierr = MatCreateVecs(F,&x,&y);CHKERRQ(ierr);
2846064a4176SStefano Zampini           ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
2847064a4176SStefano Zampini           ierr = MatMult(F,x,y);CHKERRQ(ierr);
2848064a4176SStefano Zampini           ierr = KSPSolve(kspC,y,x);CHKERRQ(ierr);
2849c0decd05SBarry Smith           ierr = KSPCheckSolve(kspC,pc,x);CHKERRQ(ierr);
2850064a4176SStefano Zampini           ierr = KSPDestroy(&kspC);CHKERRQ(ierr);
2851064a4176SStefano Zampini           ierr = MatDestroy(&F);CHKERRQ(ierr);
2852064a4176SStefano Zampini           ierr = VecDestroy(&x);CHKERRQ(ierr);
2853064a4176SStefano Zampini           ierr = VecDestroy(&y);CHKERRQ(ierr);
2854064a4176SStefano Zampini         }
2855064a4176SStefano Zampini       }
2856e1214c54Sstefano_zampini       ierr = PetscFree(ksps);CHKERRQ(ierr);
2857e1214c54Sstefano_zampini     }
28585a1e936bSStefano Zampini   }
28593425bc38SStefano Zampini   /* return pointers for objects created */
28603425bc38SStefano Zampini   *fetidp_mat = newmat;
28613425bc38SStefano Zampini   *fetidp_pc  = newpc;
28623425bc38SStefano Zampini   PetscFunctionReturn(0);
28633425bc38SStefano Zampini }
28641e6b0712SBarry Smith 
286594ef8ddeSSatish Balay /*@C
28660f202f7eSStefano Zampini  PCBDDCCreateFETIDPOperators - Create FETI-DP operators
28673425bc38SStefano Zampini 
28683425bc38SStefano Zampini    Collective
28693425bc38SStefano Zampini 
28703425bc38SStefano Zampini    Input Parameters:
28711720468bSStefano Zampini +  pc - the BDDC preconditioning context (setup should have been called before)
2872547c9a8eSstefano_zampini .  fully_redundant - true for a fully redundant set of Lagrange multipliers
2873547c9a8eSstefano_zampini -  prefix - optional options database prefix for the objects to be created (can be NULL)
287428509bceSStefano Zampini 
287528509bceSStefano Zampini    Output Parameters:
28760f202f7eSStefano Zampini +  fetidp_mat - shell FETI-DP matrix object
28770f202f7eSStefano Zampini -  fetidp_pc  - shell Dirichlet preconditioner for FETI-DP matrix
287828509bceSStefano Zampini 
28793425bc38SStefano Zampini    Level: developer
28803425bc38SStefano Zampini 
28813425bc38SStefano Zampini    Notes:
28820f202f7eSStefano Zampini      Currently the only operations provided for FETI-DP matrix are MatMult and MatMultTranspose
28833425bc38SStefano Zampini 
28840f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCMatFETIDPGetRHS, PCBDDCMatFETIDPGetSolution
28853425bc38SStefano Zampini @*/
2886547c9a8eSstefano_zampini PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc)
28873425bc38SStefano Zampini {
28883425bc38SStefano Zampini   PetscErrorCode ierr;
28893425bc38SStefano Zampini 
28903425bc38SStefano Zampini   PetscFunctionBegin;
28913425bc38SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
28923425bc38SStefano Zampini   if (pc->setupcalled) {
2893547c9a8eSstefano_zampini     ierr = PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,PetscBool,const char*,Mat*,PC*),(pc,fully_redundant,prefix,fetidp_mat,fetidp_pc));CHKERRQ(ierr);
28946080607fSStefano Zampini   } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"You must call PCSetup_BDDC() first");
28953425bc38SStefano Zampini   PetscFunctionReturn(0);
28963425bc38SStefano Zampini }
28970c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
2898da1bb401SStefano Zampini /*MC
2899da1bb401SStefano Zampini    PCBDDC - Balancing Domain Decomposition by Constraints.
29000c7d97c5SJed Brown 
290128509bceSStefano Zampini    An implementation of the BDDC preconditioner based on
290228509bceSStefano Zampini 
290328509bceSStefano Zampini .vb
290428509bceSStefano Zampini    [1] C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
290528509bceSStefano Zampini    [2] A. Klawonn and O. B. Widlund. "Dual-Primal FETI Methods for Linear Elasticity", http://cs.nyu.edu/csweb/Research/TechReports/TR2004-855/TR2004-855.pdf
290628509bceSStefano Zampini    [3] J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", http://arxiv.org/abs/0712.3977
29070f202f7eSStefano 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
290828509bceSStefano Zampini .ve
290928509bceSStefano Zampini 
291028509bceSStefano Zampini    The matrix to be preconditioned (Pmat) must be of type MATIS.
291128509bceSStefano Zampini 
29120f202f7eSStefano Zampini    Currently works with MATIS matrices with local matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers.
291328509bceSStefano Zampini 
291428509bceSStefano Zampini    It also works with unsymmetric and indefinite problems.
291528509bceSStefano Zampini 
2916b6fdb6dfSStefano 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.
2917b6fdb6dfSStefano Zampini 
2918c7017625SStefano 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).
291928509bceSStefano Zampini 
29200f202f7eSStefano 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()
292130368db7SStefano Zampini    Additional information on dofs can be provided by using PCBDDCSetDofsSplitting(), PCBDDCSetDirichletBoundaries(), PCBDDCSetNeumannBoundaries(), and PCBDDCSetPrimalVerticesIS() and their local counterparts.
292228509bceSStefano Zampini 
29230f202f7eSStefano Zampini    Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). Non-singular modes are retained via SVD.
292428509bceSStefano Zampini 
29250f202f7eSStefano 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.
29260f202f7eSStefano Zampini    User defined change of basis can be passed to PCBDDC by using PCBDDCSetChangeOfBasisMat()
292728509bceSStefano Zampini 
29280f202f7eSStefano Zampini    The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using a MatPartitioning object.
292928509bceSStefano Zampini 
2930df4d28bfSStefano 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.
293128509bceSStefano Zampini 
29320f202f7eSStefano 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.
29330f202f7eSStefano Zampini    Deluxe scaling is not supported yet for FETI-DP.
29340f202f7eSStefano Zampini 
29350f202f7eSStefano Zampini    Options Database Keys (some of them, run with -h for a complete list):
29360f202f7eSStefano Zampini 
29370f202f7eSStefano Zampini .    -pc_bddc_use_vertices <true> - use or not vertices in primal space
29380f202f7eSStefano Zampini .    -pc_bddc_use_edges <true> - use or not edges in primal space
29390f202f7eSStefano Zampini .    -pc_bddc_use_faces <false> - use or not faces in primal space
29400f202f7eSStefano Zampini .    -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems
29410f202f7eSStefano Zampini .    -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only)
29420f202f7eSStefano Zampini .    -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested
29430f202f7eSStefano Zampini .    -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1])
294428509bceSStefano Zampini .    -pc_bddc_levels <0> - maximum number of levels for multilevel
29450f202f7eSStefano 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)
29465459c157SBarry 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)
29470f202f7eSStefano Zampini .    -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling
29480f202f7eSStefano Zampini .    -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)
2949bd2a564bSStefano 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)
295028509bceSStefano Zampini -    -pc_bddc_check_level <0> - set verbosity level of debugging output
295128509bceSStefano Zampini 
295228509bceSStefano Zampini    Options for Dirichlet, Neumann or coarse solver can be set with
295328509bceSStefano Zampini .vb
295428509bceSStefano Zampini       -pc_bddc_dirichlet_
295528509bceSStefano Zampini       -pc_bddc_neumann_
295628509bceSStefano Zampini       -pc_bddc_coarse_
295728509bceSStefano Zampini .ve
29580f202f7eSStefano Zampini    e.g -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. PCBDDC uses by default KPSPREONLY and PCLU.
295928509bceSStefano Zampini 
29600f202f7eSStefano Zampini    When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified as
296128509bceSStefano Zampini .vb
2962312be037SStefano Zampini       -pc_bddc_dirichlet_lN_
2963312be037SStefano Zampini       -pc_bddc_neumann_lN_
2964312be037SStefano Zampini       -pc_bddc_coarse_lN_
296528509bceSStefano Zampini .ve
29660f202f7eSStefano Zampini    Note that level number ranges from the finest (0) to the coarsest (N).
29670f202f7eSStefano 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.
29680f202f7eSStefano Zampini .vb
29690f202f7eSStefano Zampini      -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3
29700f202f7eSStefano Zampini .ve
29710f202f7eSStefano 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
2972da1bb401SStefano Zampini 
2973da1bb401SStefano Zampini    Level: intermediate
2974da1bb401SStefano Zampini 
2975e94cfbe0SPatrick Sanan    Developer Notes:
2976da1bb401SStefano Zampini 
2977da1bb401SStefano Zampini    Contributed by Stefano Zampini
2978da1bb401SStefano Zampini 
2979da1bb401SStefano Zampini .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
2980da1bb401SStefano Zampini M*/
2981b2573a8aSBarry Smith 
29828cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
2983da1bb401SStefano Zampini {
2984da1bb401SStefano Zampini   PetscErrorCode      ierr;
2985da1bb401SStefano Zampini   PC_BDDC             *pcbddc;
2986da1bb401SStefano Zampini 
2987da1bb401SStefano Zampini   PetscFunctionBegin;
2988b00a9115SJed Brown   ierr     = PetscNewLog(pc,&pcbddc);CHKERRQ(ierr);
2989da1bb401SStefano Zampini   pc->data = (void*)pcbddc;
2990da1bb401SStefano Zampini 
2991da1bb401SStefano Zampini   /* create PCIS data structure */
2992da1bb401SStefano Zampini   ierr = PCISCreate(pc);CHKERRQ(ierr);
2993da1bb401SStefano Zampini 
29949326c5c6Sstefano_zampini   /* create local graph structure */
29959326c5c6Sstefano_zampini   ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr);
29969326c5c6Sstefano_zampini 
29979326c5c6Sstefano_zampini   /* BDDC nonzero defaults */
299808a5cf49SStefano Zampini   pcbddc->use_local_adj             = PETSC_TRUE;
299947d04d0dSStefano Zampini   pcbddc->use_vertices              = PETSC_TRUE;
300047d04d0dSStefano Zampini   pcbddc->use_edges                 = PETSC_TRUE;
30013301b35fSStefano Zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
300214f95afaSStefano Zampini   pcbddc->vertex_size               = 1;
3003c703fcc7SStefano Zampini   pcbddc->recompute_topography      = PETSC_TRUE;
300468457ee5SStefano Zampini   pcbddc->coarse_size               = -1;
300585c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
300647d04d0dSStefano Zampini   pcbddc->coarsening_ratio          = 8;
300757de7509SStefano Zampini   pcbddc->coarse_eqs_per_proc       = 1;
300827b6a85dSStefano Zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
30091e0482f5SStefano Zampini   pcbddc->nedfield                  = -1;
30101e0482f5SStefano Zampini   pcbddc->nedglobal                 = PETSC_TRUE;
3011be12c134Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
3012b96c3477SStefano Zampini   pcbddc->sub_schurs_layers         = -1;
3013bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[0]     = 0.0;
3014bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[1]     = 0.0;
3015b7eb3628SStefano Zampini 
3016da1bb401SStefano Zampini   /* function pointers */
3017da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
301893bd9ae7SStefano Zampini   pc->ops->applytranspose      = PCApplyTranspose_BDDC;
3019da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
3020da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
3021da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
30226b78500eSPatrick Sanan   pc->ops->view                = PCView_BDDC;
3023da1bb401SStefano Zampini   pc->ops->applyrichardson     = 0;
3024da1bb401SStefano Zampini   pc->ops->applysymmetricleft  = 0;
3025da1bb401SStefano Zampini   pc->ops->applysymmetricright = 0;
3026534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
3027534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
30289326c5c6Sstefano_zampini   pc->ops->reset               = PCReset_BDDC;
3029da1bb401SStefano Zampini 
3030da1bb401SStefano Zampini   /* composing function */
3031a13144ffSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",PCBDDCSetDiscreteGradient_BDDC);CHKERRQ(ierr);
3032a198735bSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",PCBDDCSetDivergenceMat_BDDC);CHKERRQ(ierr);
3033906d46d4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",PCBDDCSetChangeOfBasisMat_BDDC);CHKERRQ(ierr);
3034674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
303530368db7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",PCBDDCSetPrimalVerticesIS_BDDC);CHKERRQ(ierr);
30363100ebe3SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesLocalIS_C",PCBDDCGetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
30373100ebe3SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetPrimalVerticesIS_C",PCBDDCGetPrimalVerticesIS_BDDC);CHKERRQ(ierr);
3038bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr);
30392b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC);CHKERRQ(ierr);
3040b8ffe317SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC);CHKERRQ(ierr);
30412b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC);CHKERRQ(ierr);
3042bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
304382ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",PCBDDCSetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
3044bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
304582ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",PCBDDCSetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
3046bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
304782ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",PCBDDCGetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
3048bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
304982ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",PCBDDCGetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
3050bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
305163602bcaSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",PCBDDCSetDofsSplittingLocal_BDDC);CHKERRQ(ierr);
3052bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
3053bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr);
3054bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr);
3055bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr);
3056a06fd7f2SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",PCPreSolveChangeRHS_BDDC);CHKERRQ(ierr);
3057ab8c8b98SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",PCSetCoordinates_BDDC);CHKERRQ(ierr);
3058da1bb401SStefano Zampini   PetscFunctionReturn(0);
3059da1bb401SStefano Zampini }
306043371fb9SStefano Zampini 
306143371fb9SStefano Zampini /*@C
306243371fb9SStefano Zampini  PCBDDCInitializePackage - This function initializes everything in the PCBDDC package. It is called
30638a690491SBarry Smith     from PCInitializePackage().
306443371fb9SStefano Zampini 
306543371fb9SStefano Zampini  Level: developer
306643371fb9SStefano Zampini 
306743371fb9SStefano Zampini  .keywords: PC, PCBDDC, initialize, package
306843371fb9SStefano Zampini  .seealso: PetscInitialize()
306943371fb9SStefano Zampini @*/
307043371fb9SStefano Zampini PetscErrorCode PCBDDCInitializePackage(void)
307143371fb9SStefano Zampini {
307243371fb9SStefano Zampini   PetscErrorCode ierr;
307343371fb9SStefano Zampini   int            i;
307443371fb9SStefano Zampini 
307543371fb9SStefano Zampini   PetscFunctionBegin;
307643371fb9SStefano Zampini   if (PCBDDCPackageInitialized) PetscFunctionReturn(0);
307743371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_TRUE;
307843371fb9SStefano Zampini   ierr = PetscRegisterFinalize(PCBDDCFinalizePackage);CHKERRQ(ierr);
307943371fb9SStefano Zampini 
308043371fb9SStefano Zampini   /* general events */
308143371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCTopo",PC_CLASSID,&PC_BDDC_Topology[0]);CHKERRQ(ierr);
308243371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCLKSP",PC_CLASSID,&PC_BDDC_LocalSolvers[0]);CHKERRQ(ierr);
308343371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCLWor",PC_CLASSID,&PC_BDDC_LocalWork[0]);CHKERRQ(ierr);
308443371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCCorr",PC_CLASSID,&PC_BDDC_CorrectionSetUp[0]);CHKERRQ(ierr);
308543371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCCSet",PC_CLASSID,&PC_BDDC_CoarseSetUp[0]);CHKERRQ(ierr);
308643371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCCKSP",PC_CLASSID,&PC_BDDC_CoarseSolver[0]);CHKERRQ(ierr);
308743371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCAdap",PC_CLASSID,&PC_BDDC_AdaptiveSetUp[0]);CHKERRQ(ierr);
308843371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCScal",PC_CLASSID,&PC_BDDC_Scaling[0]);CHKERRQ(ierr);
308943371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCSchr",PC_CLASSID,&PC_BDDC_Schurs[0]);CHKERRQ(ierr);
309043371fb9SStefano Zampini   for (i=1;i<PETSC_PCBDDC_MAXLEVELS;i++) {
309143371fb9SStefano Zampini     char ename[32];
309243371fb9SStefano Zampini 
309343371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCTopo l%02d",i);CHKERRQ(ierr);
309443371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Topology[i]);CHKERRQ(ierr);
309543371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCLKSP l%02d",i);CHKERRQ(ierr);
309643371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_LocalSolvers[i]);CHKERRQ(ierr);
309743371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCLWor l%02d",i);CHKERRQ(ierr);
309843371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_LocalWork[i]);CHKERRQ(ierr);
309943371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCCorr l%02d",i);CHKERRQ(ierr);
310043371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CorrectionSetUp[i]);CHKERRQ(ierr);
310143371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCCSet l%02d",i);CHKERRQ(ierr);
310243371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CoarseSetUp[i]);CHKERRQ(ierr);
310343371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCCKSP l%02d",i);CHKERRQ(ierr);
310443371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CoarseSolver[i]);CHKERRQ(ierr);
310543371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCAdap l%02d",i);CHKERRQ(ierr);
310643371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_AdaptiveSetUp[i]);CHKERRQ(ierr);
310743371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCScal l%02d",i);CHKERRQ(ierr);
310843371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Scaling[i]);CHKERRQ(ierr);
310943371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCSchr l%02d",i);CHKERRQ(ierr);
311043371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Schurs[i]);CHKERRQ(ierr);
311143371fb9SStefano Zampini   }
311243371fb9SStefano Zampini   PetscFunctionReturn(0);
311343371fb9SStefano Zampini }
311443371fb9SStefano Zampini 
311543371fb9SStefano Zampini /*@C
311643371fb9SStefano Zampini  PCBDDCFinalizePackage - This function frees everything from the PCBDDC package. It is
311743371fb9SStefano Zampini     called from PetscFinalize() automatically.
311843371fb9SStefano Zampini 
311943371fb9SStefano Zampini  Level: developer
312043371fb9SStefano Zampini 
312143371fb9SStefano Zampini  .keywords: Petsc, destroy, package
312243371fb9SStefano Zampini  .seealso: PetscFinalize()
312343371fb9SStefano Zampini @*/
312443371fb9SStefano Zampini PetscErrorCode PCBDDCFinalizePackage(void)
312543371fb9SStefano Zampini {
312643371fb9SStefano Zampini   PetscFunctionBegin;
312743371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_FALSE;
312843371fb9SStefano Zampini   PetscFunctionReturn(0);
312943371fb9SStefano Zampini }
3130