xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 399ffe994e22ec4bff4e8fa4a49a4a09b0883c0e)
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;
58bd2a564bSStefano Zampini   PetscInt       nt;
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);
8857de7509SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_coarse_eqs_per_proc","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);
890298fd71SBarry Smith   ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","none",pcbddc->coarsening_ratio,&pcbddc->coarsening_ratio,NULL);CHKERRQ(ierr);
902b510759SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_levels","Set maximum number of levels for multilevel","none",pcbddc->max_levels,&pcbddc->max_levels,NULL);CHKERRQ(ierr);
91323d395dSStefano 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);
92674ae819SStefano 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);
93b96c3477SStefano 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);
94b96c3477SStefano 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);
95b96c3477SStefano 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);
96683d3df6SStefano 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);
97bf3a8328SStefano 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);
98839e9adbSstefano_zampini   ierr = PetscOptionsBool("-pc_bddc_deluxe_singlemat","Collapse deluxe operators","none",pcbddc->deluxe_singlemat,&pcbddc->deluxe_singlemat,NULL);CHKERRQ(ierr);
99bf3a8328SStefano 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);
100bd2a564bSStefano Zampini   nt   = 2;
101bd2a564bSStefano Zampini   ierr = PetscOptionsRealArray("-pc_bddc_adaptive_threshold","Thresholds to be used for adaptive selection of constraints","none",pcbddc->adaptive_threshold,&nt,NULL);CHKERRQ(ierr);
102bd2a564bSStefano Zampini   if (nt == 1) pcbddc->adaptive_threshold[1] = pcbddc->adaptive_threshold[0];
10308122e43SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_adaptive_nmin","Minimum number of constraints per connected components","none",pcbddc->adaptive_nmin,&pcbddc->adaptive_nmin,NULL);CHKERRQ(ierr);
10408122e43SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_adaptive_nmax","Maximum number of constraints per connected components","none",pcbddc->adaptive_nmax,&pcbddc->adaptive_nmax,NULL);CHKERRQ(ierr);
1053301b35fSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_symmetric","Symmetric computation of primal basis functions","none",pcbddc->symmetric_primal,&pcbddc->symmetric_primal,NULL);CHKERRQ(ierr);
106b0c7d250SStefano 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);
107b3afcdbeSStefano 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);
108e9627c49SStefano 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);
10927b6a85dSStefano 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);
110a198735bSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nonetflux","Automatic computation of no-net-flux quadrature weights","none",pcbddc->compute_nonetflux,&pcbddc->compute_nonetflux,NULL);CHKERRQ(ierr);
1114f1b2e48SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_detect_disconnected","Detects disconnected subdomains","none",pcbddc->detect_disconnected,&pcbddc->detect_disconnected,NULL);CHKERRQ(ierr);
1128361f951SStefano 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);
11370c64980SStefano 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);
1140c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
1150c7d97c5SJed Brown   PetscFunctionReturn(0);
1160c7d97c5SJed Brown }
1176b78500eSPatrick Sanan 
1186b78500eSPatrick Sanan static PetscErrorCode PCView_BDDC(PC pc,PetscViewer viewer)
1196b78500eSPatrick Sanan {
1206b78500eSPatrick Sanan   PC_BDDC              *pcbddc = (PC_BDDC*)pc->data;
121e9627c49SStefano Zampini   PC_IS                *pcis = (PC_IS*)pc->data;
1226b78500eSPatrick Sanan   PetscErrorCode       ierr;
12371783a16SStefano Zampini   PetscBool            isascii;
124e9627c49SStefano Zampini   PetscSubcomm         subcomm;
125e9627c49SStefano Zampini   PetscViewer          subviewer;
1266b78500eSPatrick Sanan 
1276b78500eSPatrick Sanan   PetscFunctionBegin;
1286b78500eSPatrick Sanan   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1296b78500eSPatrick Sanan   /* ASCII viewer */
1306b78500eSPatrick Sanan   if (isascii) {
1314b2aedd3SStefano Zampini     PetscMPIInt   color,rank,size;
132fbad9177SStefano Zampini     PetscInt64    loc[7],gsum[6],gmax[6],gmin[6],totbenign;
133e9627c49SStefano Zampini     PetscScalar   interface_size;
134e9627c49SStefano Zampini     PetscReal     ratio1=0.,ratio2=0.;
135e9627c49SStefano Zampini     Vec           counter;
1366b78500eSPatrick Sanan 
137b74ba07aSstefano_zampini     if (!pc->setupcalled) {
138b74ba07aSstefano_zampini       ierr = PetscViewerASCIIPrintf(viewer,"  Partial information available: preconditioner has not been setup yet\n");CHKERRQ(ierr);
139b74ba07aSstefano_zampini     }
140efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use verbose output: %D\n",pcbddc->dbg_flag);CHKERRQ(ierr);
1416f0c0a6aSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Use user-defined CSR: %d\n",!!pcbddc->mat_graph->nvtxs_csr);CHKERRQ(ierr);
1426f0c0a6aSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Use local mat graph: %d\n",pcbddc->use_local_adj && !pcbddc->mat_graph->nvtxs_csr);CHKERRQ(ierr);
143e9627c49SStefano Zampini     if (pcbddc->mat_graph->twodim) {
144efd4aadfSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Connectivity graph topological dimension: 2\n");CHKERRQ(ierr);
145e9627c49SStefano Zampini     } else {
146efd4aadfSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Connectivity graph topological dimension: 3\n");CHKERRQ(ierr);
147e9627c49SStefano Zampini     }
148aefa1729SStefano Zampini     if (pcbddc->graphmaxcount != PETSC_MAX_INT) {
149efd4aadfSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Graph max count: %D\n",pcbddc->graphmaxcount);CHKERRQ(ierr);
150aefa1729SStefano Zampini     }
15150e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Use vertices: %d (vertex size %D)\n",pcbddc->use_vertices,pcbddc->vertex_size);CHKERRQ(ierr);
152efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use edges: %d\n",pcbddc->use_edges);CHKERRQ(ierr);
153efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use faces: %d\n",pcbddc->use_faces);CHKERRQ(ierr);
154efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use true near null space: %d\n",pcbddc->use_nnsp_true);CHKERRQ(ierr);
155efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use QR for single constraints on cc: %d\n",pcbddc->use_qr_single);CHKERRQ(ierr);
156efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use change of basis on local edge nodes: %d\n",pcbddc->use_change_of_basis);CHKERRQ(ierr);
157efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use change of basis on local face nodes: %d\n",pcbddc->use_change_on_faces);CHKERRQ(ierr);
158efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  User defined change of basis matrix: %d\n",!!pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
159efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Has change of basis matrix: %d\n",!!pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
160efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Eliminate dirichlet boundary dofs: %d\n",pcbddc->eliminate_dirdofs);CHKERRQ(ierr);
161efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Switch on static condensation ops around the interface preconditioner: %d\n",pcbddc->switch_static);CHKERRQ(ierr);
162efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use exact dirichlet trick: %d\n",pcbddc->use_exact_dirichlet_trick);CHKERRQ(ierr);
16350e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Multilevel max levels: %D\n",pcbddc->max_levels);CHKERRQ(ierr);
16450e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Multilevel coarsening ratio: %D\n",pcbddc->coarsening_ratio);CHKERRQ(ierr);
165efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use estimated eigs for coarse problem: %d\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
166efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use deluxe scaling: %d\n",pcbddc->use_deluxe_scaling);CHKERRQ(ierr);
167efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use deluxe zerorows: %d\n",pcbddc->deluxe_zerorows);CHKERRQ(ierr);
168efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use deluxe singlemat: %d\n",pcbddc->deluxe_singlemat);CHKERRQ(ierr);
169efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Rebuild interface graph for Schur principal minors: %d\n",pcbddc->sub_schurs_rebuild);CHKERRQ(ierr);
17050e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Number of dofs' layers for the computation of principal minors: %D\n",pcbddc->sub_schurs_layers);CHKERRQ(ierr);
171efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use user CSR graph to compute successive layers: %d\n",pcbddc->sub_schurs_use_useradj);CHKERRQ(ierr);
172bd2a564bSStefano Zampini     if (pcbddc->adaptive_threshold[1] != pcbddc->adaptive_threshold[0]) {
173bd2a564bSStefano 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);
174bd2a564bSStefano Zampini     } else {
175bd2a564bSStefano 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);
176bd2a564bSStefano Zampini     }
17750e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Min constraints / connected component: %D\n",pcbddc->adaptive_nmin);CHKERRQ(ierr);
17850e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Max constraints / connected component: %D\n",pcbddc->adaptive_nmax);CHKERRQ(ierr);
179efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Invert exact Schur complement for adaptive selection: %d\n",pcbddc->sub_schurs_exact_schur);CHKERRQ(ierr);
180efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Symmetric computation of primal basis functions: %d\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
18150e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Num. Procs. to map coarse adjacency list: %D\n",pcbddc->coarse_adj_red);CHKERRQ(ierr);
18250e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Coarse eqs per proc (significant at the coarsest level): %D\n",pcbddc->coarse_eqs_per_proc);CHKERRQ(ierr);
1838361f951SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Detect disconnected: %d (filter %d)\n",pcbddc->detect_disconnected,pcbddc->detect_disconnected_filter);CHKERRQ(ierr);
184efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Benign subspace trick: %d (change explicit %d)\n",pcbddc->benign_saddle_point,pcbddc->benign_change_explicit);CHKERRQ(ierr);
185efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Benign subspace trick is active: %d\n",pcbddc->benign_have_null);CHKERRQ(ierr);
186efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Algebraic computation of no-net-flux %d\n",pcbddc->compute_nonetflux);CHKERRQ(ierr);
187b74ba07aSstefano_zampini     if (!pc->setupcalled) PetscFunctionReturn(0);
1886b78500eSPatrick Sanan 
189fbad9177SStefano Zampini     /* compute interface size */
190e9627c49SStefano Zampini     ierr = VecSet(pcis->vec1_B,1.0);CHKERRQ(ierr);
191e9627c49SStefano Zampini     ierr = MatCreateVecs(pc->pmat,&counter,0);CHKERRQ(ierr);
192e9627c49SStefano Zampini     ierr = VecSet(counter,0.0);CHKERRQ(ierr);
193e9627c49SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
194e9627c49SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
195e9627c49SStefano Zampini     ierr = VecSum(counter,&interface_size);CHKERRQ(ierr);
196e9627c49SStefano Zampini     ierr = VecDestroy(&counter);CHKERRQ(ierr);
197fbad9177SStefano Zampini 
198fbad9177SStefano Zampini     /* compute some statistics on the domain decomposition */
199e9627c49SStefano Zampini     gsum[0] = 1;
200fbad9177SStefano Zampini     gsum[1] = gsum[2] = gsum[3] = gsum[4] = gsum[5] = 0;
201e9627c49SStefano Zampini     loc[0]  = !!pcis->n;
202e9627c49SStefano Zampini     loc[1]  = pcis->n - pcis->n_B;
203e9627c49SStefano Zampini     loc[2]  = pcis->n_B;
204e9627c49SStefano Zampini     loc[3]  = pcbddc->local_primal_size;
205345ecf6cSStefano Zampini     loc[4]  = pcis->n;
206fbad9177SStefano Zampini     loc[5]  = pcbddc->n_local_subs > 0 ? pcbddc->n_local_subs : (pcis->n ? 1 : 0);
207fbad9177SStefano Zampini     loc[6]  = pcbddc->benign_n;
208fbad9177SStefano Zampini     ierr = MPI_Reduce(loc,gsum,6,MPIU_INT64,MPI_SUM,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
209fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = -1;
210fbad9177SStefano Zampini     ierr = MPI_Reduce(loc,gmax,6,MPIU_INT64,MPI_MAX,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
211fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = PETSC_MAX_INT;
212fbad9177SStefano Zampini     ierr = MPI_Reduce(loc,gmin,6,MPIU_INT64,MPI_MIN,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
213fbad9177SStefano Zampini     ierr = MPI_Reduce(&loc[6],&totbenign,1,MPIU_INT64,MPI_SUM,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
214e9627c49SStefano Zampini     if (pcbddc->coarse_size) {
215e9627c49SStefano Zampini       ratio1 = pc->pmat->rmap->N/(1.*pcbddc->coarse_size);
216e9627c49SStefano Zampini       ratio2 = PetscRealPart(interface_size)/pcbddc->coarse_size;
217e9627c49SStefano Zampini     }
218efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  ********************************** STATISTICS AT LEVEL %d **********************************\n",pcbddc->current_level);CHKERRQ(ierr);
21950e0721cSStefano 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);
22050e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Coarsening ratios: all/coarse %D interface/coarse %D\n",(PetscInt)ratio1,(PetscInt)ratio2);CHKERRQ(ierr);
22150e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Active processes : %D\n",(PetscInt)gsum[0]);CHKERRQ(ierr);
22250e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Total subdomains : %D\n",(PetscInt)gsum[5]);CHKERRQ(ierr);
223345ecf6cSStefano Zampini     if (pcbddc->benign_have_null) {
22450e0721cSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"  Benign subs      : %D\n",(PetscInt)totbenign);CHKERRQ(ierr);
225345ecf6cSStefano Zampini     }
22650e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Dofs type        :\tMIN\tMAX\tMEAN\n");CHKERRQ(ierr);
22750e0721cSStefano 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);
22850e0721cSStefano 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);
22950e0721cSStefano 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);
23050e0721cSStefano 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);
23150e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Local     subs   :\t%D\t%D\n"    ,(PetscInt)gmin[5],(PetscInt)gmax[5]);CHKERRQ(ierr);
23250e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  ********************************** COARSE PROBLEM DETAILS *********************************\n");CHKERRQ(ierr);
23327b6a85dSStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
234e9627c49SStefano Zampini 
235fbad9177SStefano Zampini     /* the coarse problem can be handled by a different communicator */
236e9627c49SStefano Zampini     if (pcbddc->coarse_ksp) color = 1;
237e9627c49SStefano Zampini     else color = 0;
238e9627c49SStefano Zampini     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
2394b2aedd3SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
240e9627c49SStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)pc),&subcomm);CHKERRQ(ierr);
2414b2aedd3SStefano Zampini     ierr = PetscSubcommSetNumber(subcomm,PetscMin(size,2));CHKERRQ(ierr);
242e9627c49SStefano Zampini     ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
243e9627c49SStefano Zampini     ierr = PetscViewerGetSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer);CHKERRQ(ierr);
244e9627c49SStefano Zampini     if (color == 1) {
245e9627c49SStefano Zampini       ierr = KSPView(pcbddc->coarse_ksp,subviewer);CHKERRQ(ierr);
246e9627c49SStefano Zampini       ierr = PetscViewerFlush(subviewer);CHKERRQ(ierr);
247e9627c49SStefano Zampini     }
248e9627c49SStefano Zampini     ierr = PetscViewerRestoreSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer);CHKERRQ(ierr);
249e9627c49SStefano Zampini     ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
250e9627c49SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
251e9627c49SStefano Zampini   }
2526b78500eSPatrick Sanan   PetscFunctionReturn(0);
2536b78500eSPatrick Sanan }
254a13144ffSStefano Zampini 
2551e0482f5SStefano Zampini static PetscErrorCode PCBDDCSetDiscreteGradient_BDDC(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
256a13144ffSStefano Zampini {
257a13144ffSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
258a13144ffSStefano Zampini   PetscErrorCode ierr;
259a13144ffSStefano Zampini 
260a13144ffSStefano Zampini   PetscFunctionBegin;
261a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)G);CHKERRQ(ierr);
262a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
263a13144ffSStefano Zampini   pcbddc->discretegradient = G;
264a13144ffSStefano Zampini   pcbddc->nedorder         = order > 0 ? order : -order;
265495a2a07SStefano Zampini   pcbddc->nedfield         = field;
2661e0482f5SStefano Zampini   pcbddc->nedglobal        = global;
2671e0482f5SStefano Zampini   pcbddc->conforming       = conforming;
268a13144ffSStefano Zampini   PetscFunctionReturn(0);
269a13144ffSStefano Zampini }
270a13144ffSStefano Zampini 
271a13144ffSStefano Zampini /*@
272a13144ffSStefano Zampini  PCBDDCSetDiscreteGradient - Sets the discrete gradient
273a13144ffSStefano Zampini 
274a13144ffSStefano Zampini    Collective on PC
275a13144ffSStefano Zampini 
276a13144ffSStefano Zampini    Input Parameters:
277a13144ffSStefano Zampini +  pc         - the preconditioning context
278a13144ffSStefano Zampini .  G          - the discrete gradient matrix (should be in AIJ format)
279a13144ffSStefano Zampini .  order      - the order of the Nedelec space (1 for the lowest order)
280495a2a07SStefano Zampini .  field      - the field id of the Nedelec dofs (not used if the fields have not been specified)
2811e0482f5SStefano Zampini .  global     - the type of global ordering for the rows of G
282a13144ffSStefano Zampini -  conforming - whether the mesh is conforming or not
283a13144ffSStefano Zampini 
284a13144ffSStefano Zampini    Level: advanced
285a13144ffSStefano Zampini 
28695452b02SPatrick Sanan    Notes:
28795452b02SPatrick Sanan     The discrete gradient matrix G is used to analyze the subdomain edges, and it should not contain any zero entry.
288495a2a07SStefano Zampini           For variable order spaces, the order should be set to zero.
2891e0482f5SStefano Zampini           If global is true, the rows of G should be given in global ordering for the whole dofs;
2901e0482f5SStefano Zampini           if false, the ordering should be global for the Nedelec field.
2911e0482f5SStefano 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
2921e0482f5SStefano Zampini           and geid the one for the Nedelec field.
293a13144ffSStefano Zampini 
294495a2a07SStefano Zampini .seealso: PCBDDC,PCBDDCSetDofsSplitting(),PCBDDCSetDofsSplittingLocal()
295a13144ffSStefano Zampini @*/
2961e0482f5SStefano Zampini PetscErrorCode PCBDDCSetDiscreteGradient(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
297a13144ffSStefano Zampini {
298a13144ffSStefano Zampini   PetscErrorCode ierr;
299a13144ffSStefano Zampini 
300a13144ffSStefano Zampini   PetscFunctionBegin;
301a13144ffSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
302a13144ffSStefano Zampini   PetscValidHeaderSpecific(G,MAT_CLASSID,2);
303a13144ffSStefano Zampini   PetscValidLogicalCollectiveInt(pc,order,3);
3041e0482f5SStefano Zampini   PetscValidLogicalCollectiveInt(pc,field,4);
3051e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc,global,5);
3061e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc,conforming,6);
3071e0482f5SStefano Zampini   PetscCheckSameComm(pc,1,G,2);
3081e0482f5SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDiscreteGradient_C",(PC,Mat,PetscInt,PetscInt,PetscBool,PetscBool),(pc,G,order,field,global,conforming));CHKERRQ(ierr);
309a13144ffSStefano Zampini   PetscFunctionReturn(0);
310a13144ffSStefano Zampini }
311a13144ffSStefano Zampini 
3128ae0ca82SStefano Zampini static PetscErrorCode PCBDDCSetDivergenceMat_BDDC(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
313a198735bSStefano Zampini {
314a198735bSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
315a198735bSStefano Zampini   PetscErrorCode ierr;
3166b78500eSPatrick Sanan 
317a198735bSStefano Zampini   PetscFunctionBegin;
318a198735bSStefano Zampini   ierr = PetscObjectReference((PetscObject)divudotp);CHKERRQ(ierr);
319a198735bSStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
320a198735bSStefano Zampini   pcbddc->divudotp = divudotp;
3218ae0ca82SStefano Zampini   pcbddc->divudotp_trans = trans;
322a198735bSStefano Zampini   pcbddc->compute_nonetflux = PETSC_TRUE;
323a198735bSStefano Zampini   if (vl2l) {
324a198735bSStefano Zampini     ierr = PetscObjectReference((PetscObject)vl2l);CHKERRQ(ierr);
325fa23a32eSStefano Zampini     ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
326a198735bSStefano Zampini     pcbddc->divudotp_vl2l = vl2l;
327a198735bSStefano Zampini   }
328a198735bSStefano Zampini   PetscFunctionReturn(0);
329a198735bSStefano Zampini }
3303d996552SStefano Zampini 
331a198735bSStefano Zampini /*@
332a198735bSStefano Zampini  PCBDDCSetDivergenceMat - Sets the linear operator representing \int_\Omega \div {\bf u} \cdot p dx
333a198735bSStefano Zampini 
334a198735bSStefano Zampini    Collective on PC
335a198735bSStefano Zampini 
336a198735bSStefano Zampini    Input Parameters:
337a198735bSStefano Zampini +  pc - the preconditioning context
338a198735bSStefano Zampini .  divudotp - the matrix (must be of type MATIS)
3398ae0ca82SStefano Zampini .  trans - if trans if false (resp. true), then pressures are in the test (trial) space and velocities are in the trial (test) space.
34005a3bf82SStefano 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
341a198735bSStefano Zampini 
342a198735bSStefano Zampini    Level: advanced
343a198735bSStefano Zampini 
34495452b02SPatrick Sanan    Notes:
34595452b02SPatrick Sanan     This auxiliary matrix is used to compute quadrature weights representing the net-flux across subdomain boundaries
34605a3bf82SStefano Zampini           If vl2l is NULL, the local ordering for velocities in divudotp should match that of the preconditioning matrix
347a198735bSStefano Zampini 
348a198735bSStefano Zampini .seealso: PCBDDC
349a198735bSStefano Zampini @*/
3508ae0ca82SStefano Zampini PetscErrorCode PCBDDCSetDivergenceMat(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
351a198735bSStefano Zampini {
352a198735bSStefano Zampini   PetscBool      ismatis;
353a198735bSStefano Zampini   PetscErrorCode ierr;
354a198735bSStefano Zampini 
355a198735bSStefano Zampini   PetscFunctionBegin;
356a198735bSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
357a198735bSStefano Zampini   PetscValidHeaderSpecific(divudotp,MAT_CLASSID,2);
358a198735bSStefano Zampini   PetscCheckSameComm(pc,1,divudotp,2);
3598ae0ca82SStefano Zampini   PetscValidLogicalCollectiveBool(pc,trans,3);
3608ae0ca82SStefano Zampini   if (vl2l) PetscValidHeaderSpecific(divudotp,IS_CLASSID,4);
361a198735bSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)divudotp,MATIS,&ismatis);CHKERRQ(ierr);
362a198735bSStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Divergence matrix needs to be of type MATIS");
3638ae0ca82SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDivergenceMat_C",(PC,Mat,PetscBool,IS),(pc,divudotp,trans,vl2l));CHKERRQ(ierr);
364a198735bSStefano Zampini   PetscFunctionReturn(0);
365a198735bSStefano Zampini }
3662d505d7fSStefano Zampini 
3671dd7afcfSStefano Zampini static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change, PetscBool interior)
368b9b85e73SStefano Zampini {
369b9b85e73SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
370b9b85e73SStefano Zampini   PetscErrorCode ierr;
371b9b85e73SStefano Zampini 
372b9b85e73SStefano Zampini   PetscFunctionBegin;
373b9b85e73SStefano Zampini   ierr = PetscObjectReference((PetscObject)change);CHKERRQ(ierr);
37456282151SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
375b9b85e73SStefano Zampini   pcbddc->user_ChangeOfBasisMatrix = change;
3761dd7afcfSStefano Zampini   pcbddc->change_interior = interior;
377b9b85e73SStefano Zampini   PetscFunctionReturn(0);
378b9b85e73SStefano Zampini }
379b9b85e73SStefano Zampini /*@
380906d46d4SStefano Zampini  PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs
381b9b85e73SStefano Zampini 
382b9b85e73SStefano Zampini    Collective on PC
383b9b85e73SStefano Zampini 
384b9b85e73SStefano Zampini    Input Parameters:
385b9b85e73SStefano Zampini +  pc - the preconditioning context
3861dd7afcfSStefano Zampini .  change - the change of basis matrix
3871dd7afcfSStefano Zampini -  interior - whether or not the change of basis modifies interior dofs
388b9b85e73SStefano Zampini 
389b9b85e73SStefano Zampini    Level: intermediate
390b9b85e73SStefano Zampini 
391b9b85e73SStefano Zampini    Notes:
392b9b85e73SStefano Zampini 
393b9b85e73SStefano Zampini .seealso: PCBDDC
394b9b85e73SStefano Zampini @*/
3951dd7afcfSStefano Zampini PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change, PetscBool interior)
396b9b85e73SStefano Zampini {
397b9b85e73SStefano Zampini   PetscErrorCode ierr;
398b9b85e73SStefano Zampini 
399b9b85e73SStefano Zampini   PetscFunctionBegin;
400b9b85e73SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
401b9b85e73SStefano Zampini   PetscValidHeaderSpecific(change,MAT_CLASSID,2);
402906d46d4SStefano Zampini   PetscCheckSameComm(pc,1,change,2);
403906d46d4SStefano Zampini   if (pc->mat) {
404906d46d4SStefano Zampini     PetscInt rows_c,cols_c,rows,cols;
405906d46d4SStefano Zampini     ierr = MatGetSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
406906d46d4SStefano Zampini     ierr = MatGetSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
407e0fe2d75SToby 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);
408e0fe2d75SToby 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);
409906d46d4SStefano Zampini     ierr = MatGetLocalSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
410906d46d4SStefano Zampini     ierr = MatGetLocalSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
411e0fe2d75SToby 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);
412e0fe2d75SToby 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);
413906d46d4SStefano Zampini   }
4141dd7afcfSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetChangeOfBasisMat_C",(PC,Mat,PetscBool),(pc,change,interior));CHKERRQ(ierr);
415b9b85e73SStefano Zampini   PetscFunctionReturn(0);
416b9b85e73SStefano Zampini }
4172d505d7fSStefano Zampini 
41830368db7SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesIS_BDDC(PC pc, IS PrimalVertices)
41930368db7SStefano Zampini {
42030368db7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
42156282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
42230368db7SStefano Zampini   PetscErrorCode ierr;
42330368db7SStefano Zampini 
42430368db7SStefano Zampini   PetscFunctionBegin;
42556282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
42656282151SStefano Zampini   if (pcbddc->user_primal_vertices) {
42756282151SStefano Zampini     ierr = ISEqual(PrimalVertices,pcbddc->user_primal_vertices,&isequal);CHKERRQ(ierr);
42856282151SStefano Zampini   }
42930368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
43030368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
43130368db7SStefano Zampini   pcbddc->user_primal_vertices = PrimalVertices;
43256282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
43330368db7SStefano Zampini   PetscFunctionReturn(0);
43430368db7SStefano Zampini }
435ab8c8b98SStefano Zampini 
43630368db7SStefano Zampini /*@
43730368db7SStefano Zampini  PCBDDCSetPrimalVerticesIS - Set additional user defined primal vertices in PCBDDC
43830368db7SStefano Zampini 
43930368db7SStefano Zampini    Collective
44030368db7SStefano Zampini 
44130368db7SStefano Zampini    Input Parameters:
44230368db7SStefano Zampini +  pc - the preconditioning context
44330368db7SStefano Zampini -  PrimalVertices - index set of primal vertices in global numbering (can be empty)
44430368db7SStefano Zampini 
44530368db7SStefano Zampini    Level: intermediate
44630368db7SStefano Zampini 
44730368db7SStefano Zampini    Notes:
44830368db7SStefano Zampini      Any process can list any global node
44930368db7SStefano Zampini 
45030368db7SStefano Zampini .seealso: PCBDDC
45130368db7SStefano Zampini @*/
45230368db7SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesIS(PC pc, IS PrimalVertices)
45330368db7SStefano Zampini {
45430368db7SStefano Zampini   PetscErrorCode ierr;
45530368db7SStefano Zampini 
45630368db7SStefano Zampini   PetscFunctionBegin;
45730368db7SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
45830368db7SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
45930368db7SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
46030368db7SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
46130368db7SStefano Zampini   PetscFunctionReturn(0);
46230368db7SStefano Zampini }
4632d505d7fSStefano Zampini 
464674ae819SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
465674ae819SStefano Zampini {
466674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
46756282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
468674ae819SStefano Zampini   PetscErrorCode ierr;
4691e6b0712SBarry Smith 
470674ae819SStefano Zampini   PetscFunctionBegin;
47156282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
47256282151SStefano Zampini   if (pcbddc->user_primal_vertices_local) {
47356282151SStefano Zampini     ierr = ISEqual(PrimalVertices,pcbddc->user_primal_vertices_local,&isequal);CHKERRQ(ierr);
47456282151SStefano Zampini   }
475674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
47630368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
47730368db7SStefano Zampini   pcbddc->user_primal_vertices_local = PrimalVertices;
47856282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
479674ae819SStefano Zampini   PetscFunctionReturn(0);
480674ae819SStefano Zampini }
481674ae819SStefano Zampini /*@
48228509bceSStefano Zampini  PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in PCBDDC
483674ae819SStefano Zampini 
48417eb1463SStefano Zampini    Collective
485674ae819SStefano Zampini 
486674ae819SStefano Zampini    Input Parameters:
487674ae819SStefano Zampini +  pc - the preconditioning context
48817eb1463SStefano Zampini -  PrimalVertices - index set of primal vertices in local numbering (can be empty)
489674ae819SStefano Zampini 
490674ae819SStefano Zampini    Level: intermediate
491674ae819SStefano Zampini 
492674ae819SStefano Zampini    Notes:
493674ae819SStefano Zampini 
494674ae819SStefano Zampini .seealso: PCBDDC
495674ae819SStefano Zampini @*/
496674ae819SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
497674ae819SStefano Zampini {
498674ae819SStefano Zampini   PetscErrorCode ierr;
499674ae819SStefano Zampini 
500674ae819SStefano Zampini   PetscFunctionBegin;
501674ae819SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
502674ae819SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
50317eb1463SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
504674ae819SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
505674ae819SStefano Zampini   PetscFunctionReturn(0);
506674ae819SStefano Zampini }
5072d505d7fSStefano Zampini 
5084fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k)
5094fad6a16SStefano Zampini {
5104fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
5114fad6a16SStefano Zampini 
5124fad6a16SStefano Zampini   PetscFunctionBegin;
5134fad6a16SStefano Zampini   pcbddc->coarsening_ratio = k;
5144fad6a16SStefano Zampini   PetscFunctionReturn(0);
5154fad6a16SStefano Zampini }
5161e6b0712SBarry Smith 
5174fad6a16SStefano Zampini /*@
51828509bceSStefano Zampini  PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel
5194fad6a16SStefano Zampini 
5204fad6a16SStefano Zampini    Logically collective on PC
5214fad6a16SStefano Zampini 
5224fad6a16SStefano Zampini    Input Parameters:
5234fad6a16SStefano Zampini +  pc - the preconditioning context
52428509bceSStefano Zampini -  k - coarsening ratio (H/h at the coarser level)
5254fad6a16SStefano Zampini 
5260f202f7eSStefano Zampini    Options Database Keys:
5270f202f7eSStefano Zampini .    -pc_bddc_coarsening_ratio
5284fad6a16SStefano Zampini 
5294fad6a16SStefano Zampini    Level: intermediate
5304fad6a16SStefano Zampini 
5314fad6a16SStefano Zampini    Notes:
5320f202f7eSStefano Zampini      Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level
5334fad6a16SStefano Zampini 
5340f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetLevels()
5354fad6a16SStefano Zampini @*/
5364fad6a16SStefano Zampini PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k)
5374fad6a16SStefano Zampini {
5384fad6a16SStefano Zampini   PetscErrorCode ierr;
5394fad6a16SStefano Zampini 
5404fad6a16SStefano Zampini   PetscFunctionBegin;
5414fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5422b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,k,2);
5434fad6a16SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));CHKERRQ(ierr);
5444fad6a16SStefano Zampini   PetscFunctionReturn(0);
5454fad6a16SStefano Zampini }
5462b510759SStefano Zampini 
547b8ffe317SStefano Zampini /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */
548b8ffe317SStefano Zampini static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc,PetscBool flg)
549b8ffe317SStefano Zampini {
550b8ffe317SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
551b8ffe317SStefano Zampini 
552b8ffe317SStefano Zampini   PetscFunctionBegin;
55385c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = flg;
554b8ffe317SStefano Zampini   PetscFunctionReturn(0);
555b8ffe317SStefano Zampini }
556b8ffe317SStefano Zampini 
557b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool flg)
5582b510759SStefano Zampini {
5592b510759SStefano Zampini   PetscErrorCode ierr;
5602b510759SStefano Zampini 
5612b510759SStefano Zampini   PetscFunctionBegin;
5622b510759SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
563b8ffe317SStefano Zampini   PetscValidLogicalCollectiveBool(pc,flg,2);
564b8ffe317SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetUseExactDirichlet_C",(PC,PetscBool),(pc,flg));CHKERRQ(ierr);
5652b510759SStefano Zampini   PetscFunctionReturn(0);
5662b510759SStefano Zampini }
5671e6b0712SBarry Smith 
5682b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc,PetscInt level)
5694fad6a16SStefano Zampini {
5704fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
5714fad6a16SStefano Zampini 
5724fad6a16SStefano Zampini   PetscFunctionBegin;
5732b510759SStefano Zampini   pcbddc->current_level = level;
5744fad6a16SStefano Zampini   PetscFunctionReturn(0);
5754fad6a16SStefano Zampini }
5761e6b0712SBarry Smith 
577b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level)
578b8ffe317SStefano Zampini {
579b8ffe317SStefano Zampini   PetscErrorCode ierr;
580b8ffe317SStefano Zampini 
581b8ffe317SStefano Zampini   PetscFunctionBegin;
582b8ffe317SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
583b8ffe317SStefano Zampini   PetscValidLogicalCollectiveInt(pc,level,2);
584b8ffe317SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLevel_C",(PC,PetscInt),(pc,level));CHKERRQ(ierr);
585b8ffe317SStefano Zampini   PetscFunctionReturn(0);
586b8ffe317SStefano Zampini }
587b8ffe317SStefano Zampini 
5882b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc,PetscInt levels)
5892b510759SStefano Zampini {
5902b510759SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
5912b510759SStefano Zampini 
5922b510759SStefano Zampini   PetscFunctionBegin;
5932b510759SStefano Zampini   pcbddc->max_levels = levels;
5942b510759SStefano Zampini   PetscFunctionReturn(0);
5952b510759SStefano Zampini }
5962b510759SStefano Zampini 
5974fad6a16SStefano Zampini /*@
59837ebbdf7SStefano Zampini  PCBDDCSetLevels - Sets the maximum number of additional levels allowed for multilevel BDDC
5994fad6a16SStefano Zampini 
6004fad6a16SStefano Zampini    Logically collective on PC
6014fad6a16SStefano Zampini 
6024fad6a16SStefano Zampini    Input Parameters:
6034fad6a16SStefano Zampini +  pc - the preconditioning context
60437ebbdf7SStefano Zampini -  levels - the maximum number of levels
6054fad6a16SStefano Zampini 
6060f202f7eSStefano Zampini    Options Database Keys:
6070f202f7eSStefano Zampini .    -pc_bddc_levels
6084fad6a16SStefano Zampini 
6094fad6a16SStefano Zampini    Level: intermediate
6104fad6a16SStefano Zampini 
6114fad6a16SStefano Zampini    Notes:
61237ebbdf7SStefano Zampini      The default value is 0, that gives the classical two-levels BDDC
6134fad6a16SStefano Zampini 
6140f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetCoarseningRatio()
6154fad6a16SStefano Zampini @*/
6162b510759SStefano Zampini PetscErrorCode PCBDDCSetLevels(PC pc,PetscInt levels)
6174fad6a16SStefano Zampini {
6184fad6a16SStefano Zampini   PetscErrorCode ierr;
6194fad6a16SStefano Zampini 
6204fad6a16SStefano Zampini   PetscFunctionBegin;
6214fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
6222b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,levels,2);
62337ebbdf7SStefano Zampini   if (levels > PETSC_PCBDDC_MAXLEVELS-1) SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Maximum number of additional levels for BDDC is %d\n",PETSC_PCBDDC_MAXLEVELS-1);
6242b510759SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLevels_C",(PC,PetscInt),(pc,levels));CHKERRQ(ierr);
6254fad6a16SStefano Zampini   PetscFunctionReturn(0);
6264fad6a16SStefano Zampini }
6271e6b0712SBarry Smith 
6283b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
6293b03a366Sstefano_zampini {
6303b03a366Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
63156282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
6323b03a366Sstefano_zampini   PetscErrorCode ierr;
6333b03a366Sstefano_zampini 
6343b03a366Sstefano_zampini   PetscFunctionBegin;
63556282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
63656282151SStefano Zampini   if (pcbddc->DirichletBoundaries) {
63756282151SStefano Zampini     ierr = ISEqual(DirichletBoundaries,pcbddc->DirichletBoundaries,&isequal);CHKERRQ(ierr);
63856282151SStefano Zampini   }
639785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
640785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
6413b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
64236e030ebSStefano Zampini   pcbddc->DirichletBoundaries = DirichletBoundaries;
64356282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
6443b03a366Sstefano_zampini   PetscFunctionReturn(0);
6453b03a366Sstefano_zampini }
6461e6b0712SBarry Smith 
6473b03a366Sstefano_zampini /*@
64828509bceSStefano Zampini  PCBDDCSetDirichletBoundaries - Set IS defining Dirichlet boundaries for the global problem.
6493b03a366Sstefano_zampini 
650785d1243SStefano Zampini    Collective
6513b03a366Sstefano_zampini 
6523b03a366Sstefano_zampini    Input Parameters:
6533b03a366Sstefano_zampini +  pc - the preconditioning context
654785d1243SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries
6553b03a366Sstefano_zampini 
6563b03a366Sstefano_zampini    Level: intermediate
6573b03a366Sstefano_zampini 
6580f202f7eSStefano Zampini    Notes:
6590f202f7eSStefano Zampini      Provide the information if you used MatZeroRows/Columns routines. Any process can list any global node
6603b03a366Sstefano_zampini 
6610f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetDirichletBoundariesLocal(), MatZeroRows(), MatZeroRowsColumns()
6623b03a366Sstefano_zampini @*/
6633b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
6643b03a366Sstefano_zampini {
6653b03a366Sstefano_zampini   PetscErrorCode ierr;
6663b03a366Sstefano_zampini 
6673b03a366Sstefano_zampini   PetscFunctionBegin;
6683b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
669674ae819SStefano Zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
670785d1243SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
6713b03a366Sstefano_zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
6723b03a366Sstefano_zampini   PetscFunctionReturn(0);
6733b03a366Sstefano_zampini }
6741e6b0712SBarry Smith 
67582ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc,IS DirichletBoundaries)
6763b03a366Sstefano_zampini {
6773b03a366Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
67856282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
6793b03a366Sstefano_zampini   PetscErrorCode ierr;
6803b03a366Sstefano_zampini 
6813b03a366Sstefano_zampini   PetscFunctionBegin;
68256282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
68356282151SStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
68456282151SStefano Zampini     ierr = ISEqual(DirichletBoundaries,pcbddc->DirichletBoundariesLocal,&isequal);CHKERRQ(ierr);
68556282151SStefano Zampini   }
686785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
687785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
6883b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
689785d1243SStefano Zampini   pcbddc->DirichletBoundariesLocal = DirichletBoundaries;
69056282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
6913b03a366Sstefano_zampini   PetscFunctionReturn(0);
6923b03a366Sstefano_zampini }
6933b03a366Sstefano_zampini 
6943b03a366Sstefano_zampini /*@
69582ba6b80SStefano Zampini  PCBDDCSetDirichletBoundariesLocal - Set IS defining Dirichlet boundaries for the global problem in local ordering.
6963b03a366Sstefano_zampini 
697785d1243SStefano Zampini    Collective
6983b03a366Sstefano_zampini 
6993b03a366Sstefano_zampini    Input Parameters:
7003b03a366Sstefano_zampini +  pc - the preconditioning context
70182ba6b80SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries (in local ordering)
7023b03a366Sstefano_zampini 
7033b03a366Sstefano_zampini    Level: intermediate
7043b03a366Sstefano_zampini 
7053b03a366Sstefano_zampini    Notes:
7063b03a366Sstefano_zampini 
7070f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetDirichletBoundaries(), MatZeroRows(), MatZeroRowsColumns()
7083b03a366Sstefano_zampini @*/
70982ba6b80SStefano Zampini PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc,IS DirichletBoundaries)
7103b03a366Sstefano_zampini {
7113b03a366Sstefano_zampini   PetscErrorCode ierr;
7123b03a366Sstefano_zampini 
7133b03a366Sstefano_zampini   PetscFunctionBegin;
7143b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
7153b03a366Sstefano_zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
71682ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
71782ba6b80SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundariesLocal_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
7183b03a366Sstefano_zampini   PetscFunctionReturn(0);
7193b03a366Sstefano_zampini }
7203b03a366Sstefano_zampini 
72153cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
7220c7d97c5SJed Brown {
7230c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
72456282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
72553cdbc3dSStefano Zampini   PetscErrorCode ierr;
7260c7d97c5SJed Brown 
7270c7d97c5SJed Brown   PetscFunctionBegin;
72856282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
72956282151SStefano Zampini   if (pcbddc->NeumannBoundaries) {
73056282151SStefano Zampini     ierr = ISEqual(NeumannBoundaries,pcbddc->NeumannBoundaries,&isequal);CHKERRQ(ierr);
73156282151SStefano Zampini   }
732785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
733785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
73453cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
73536e030ebSStefano Zampini   pcbddc->NeumannBoundaries = NeumannBoundaries;
73656282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7370c7d97c5SJed Brown   PetscFunctionReturn(0);
7380c7d97c5SJed Brown }
7391e6b0712SBarry Smith 
74057527edcSJed Brown /*@
74128509bceSStefano Zampini  PCBDDCSetNeumannBoundaries - Set IS defining Neumann boundaries for the global problem.
74257527edcSJed Brown 
743785d1243SStefano Zampini    Collective
74457527edcSJed Brown 
74557527edcSJed Brown    Input Parameters:
74657527edcSJed Brown +  pc - the preconditioning context
747785d1243SStefano Zampini -  NeumannBoundaries - parallel IS defining the Neumann boundaries
74857527edcSJed Brown 
74957527edcSJed Brown    Level: intermediate
75057527edcSJed Brown 
7510f202f7eSStefano Zampini    Notes:
7520f202f7eSStefano Zampini      Any process can list any global node
75357527edcSJed Brown 
7540f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetNeumannBoundariesLocal()
75557527edcSJed Brown @*/
75653cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
7570c7d97c5SJed Brown {
7580c7d97c5SJed Brown   PetscErrorCode ierr;
7590c7d97c5SJed Brown 
7600c7d97c5SJed Brown   PetscFunctionBegin;
7610c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
762674ae819SStefano Zampini   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
763785d1243SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
76453cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
76553cdbc3dSStefano Zampini   PetscFunctionReturn(0);
76653cdbc3dSStefano Zampini }
7671e6b0712SBarry Smith 
76882ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc,IS NeumannBoundaries)
7690c7d97c5SJed Brown {
7700c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
77156282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
7720c7d97c5SJed Brown   PetscErrorCode ierr;
7730c7d97c5SJed Brown 
7740c7d97c5SJed Brown   PetscFunctionBegin;
77556282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
77656282151SStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
77756282151SStefano Zampini     ierr = ISEqual(NeumannBoundaries,pcbddc->NeumannBoundariesLocal,&isequal);CHKERRQ(ierr);
77856282151SStefano Zampini   }
779785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
780785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
7810c7d97c5SJed Brown   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
782785d1243SStefano Zampini   pcbddc->NeumannBoundariesLocal = NeumannBoundaries;
78356282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7840c7d97c5SJed Brown   PetscFunctionReturn(0);
7850c7d97c5SJed Brown }
7860c7d97c5SJed Brown 
7870c7d97c5SJed Brown /*@
78882ba6b80SStefano Zampini  PCBDDCSetNeumannBoundariesLocal - Set IS defining Neumann boundaries for the global problem in local ordering.
7890c7d97c5SJed Brown 
790785d1243SStefano Zampini    Collective
7910c7d97c5SJed Brown 
7920c7d97c5SJed Brown    Input Parameters:
7930c7d97c5SJed Brown +  pc - the preconditioning context
79482ba6b80SStefano Zampini -  NeumannBoundaries - parallel IS defining the subdomain part of Neumann boundaries (in local ordering)
7950c7d97c5SJed Brown 
7960c7d97c5SJed Brown    Level: intermediate
7970c7d97c5SJed Brown 
7980c7d97c5SJed Brown    Notes:
7990c7d97c5SJed Brown 
8000f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetNeumannBoundaries()
8010c7d97c5SJed Brown @*/
80282ba6b80SStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc,IS NeumannBoundaries)
8030c7d97c5SJed Brown {
8040c7d97c5SJed Brown   PetscErrorCode ierr;
8050c7d97c5SJed Brown 
8060c7d97c5SJed Brown   PetscFunctionBegin;
8070c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
8080c7d97c5SJed Brown   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
80982ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
81082ba6b80SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundariesLocal_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
81153cdbc3dSStefano Zampini   PetscFunctionReturn(0);
81253cdbc3dSStefano Zampini }
81353cdbc3dSStefano Zampini 
814da1bb401SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
815da1bb401SStefano Zampini {
816da1bb401SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
817da1bb401SStefano Zampini 
818da1bb401SStefano Zampini   PetscFunctionBegin;
819da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
820da1bb401SStefano Zampini   PetscFunctionReturn(0);
821da1bb401SStefano Zampini }
8221e6b0712SBarry Smith 
823da1bb401SStefano Zampini /*@
824785d1243SStefano Zampini  PCBDDCGetDirichletBoundaries - Get parallel IS for Dirichlet boundaries
825da1bb401SStefano Zampini 
826785d1243SStefano Zampini    Collective
827785d1243SStefano Zampini 
828785d1243SStefano Zampini    Input Parameters:
829785d1243SStefano Zampini .  pc - the preconditioning context
830785d1243SStefano Zampini 
831785d1243SStefano Zampini    Output Parameters:
832785d1243SStefano Zampini .  DirichletBoundaries - index set defining the Dirichlet boundaries
833785d1243SStefano Zampini 
834785d1243SStefano Zampini    Level: intermediate
835785d1243SStefano Zampini 
8360f202f7eSStefano Zampini    Notes:
8370f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetDirichletBoundaries
838785d1243SStefano Zampini 
839785d1243SStefano Zampini .seealso: PCBDDC
840785d1243SStefano Zampini @*/
841785d1243SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
842785d1243SStefano Zampini {
843785d1243SStefano Zampini   PetscErrorCode ierr;
844785d1243SStefano Zampini 
845785d1243SStefano Zampini   PetscFunctionBegin;
846785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
847785d1243SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
848785d1243SStefano Zampini   PetscFunctionReturn(0);
849785d1243SStefano Zampini }
850785d1243SStefano Zampini 
851785d1243SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc,IS *DirichletBoundaries)
852785d1243SStefano Zampini {
853785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
854785d1243SStefano Zampini 
855785d1243SStefano Zampini   PetscFunctionBegin;
856785d1243SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundariesLocal;
857785d1243SStefano Zampini   PetscFunctionReturn(0);
858785d1243SStefano Zampini }
859785d1243SStefano Zampini 
860da1bb401SStefano Zampini /*@
86182ba6b80SStefano Zampini  PCBDDCGetDirichletBoundariesLocal - Get parallel IS for Dirichlet boundaries (in local ordering)
862da1bb401SStefano Zampini 
863785d1243SStefano Zampini    Collective
864da1bb401SStefano Zampini 
865da1bb401SStefano Zampini    Input Parameters:
86628509bceSStefano Zampini .  pc - the preconditioning context
867da1bb401SStefano Zampini 
868da1bb401SStefano Zampini    Output Parameters:
86928509bceSStefano Zampini .  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
870da1bb401SStefano Zampini 
871da1bb401SStefano Zampini    Level: intermediate
872da1bb401SStefano Zampini 
873da1bb401SStefano Zampini    Notes:
8740f202f7eSStefano 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).
8750f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
876da1bb401SStefano Zampini 
877da1bb401SStefano Zampini .seealso: PCBDDC
878da1bb401SStefano Zampini @*/
87982ba6b80SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc,IS *DirichletBoundaries)
880da1bb401SStefano Zampini {
881da1bb401SStefano Zampini   PetscErrorCode ierr;
882da1bb401SStefano Zampini 
883da1bb401SStefano Zampini   PetscFunctionBegin;
884da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
88582ba6b80SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundariesLocal_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
886da1bb401SStefano Zampini   PetscFunctionReturn(0);
887da1bb401SStefano Zampini }
8881e6b0712SBarry Smith 
88953cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
89053cdbc3dSStefano Zampini {
89153cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
89253cdbc3dSStefano Zampini 
89353cdbc3dSStefano Zampini   PetscFunctionBegin;
89453cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
89553cdbc3dSStefano Zampini   PetscFunctionReturn(0);
89653cdbc3dSStefano Zampini }
8971e6b0712SBarry Smith 
89853cdbc3dSStefano Zampini /*@
899785d1243SStefano Zampini  PCBDDCGetNeumannBoundaries - Get parallel IS for Neumann boundaries
90053cdbc3dSStefano Zampini 
901785d1243SStefano Zampini    Collective
902785d1243SStefano Zampini 
903785d1243SStefano Zampini    Input Parameters:
904785d1243SStefano Zampini .  pc - the preconditioning context
905785d1243SStefano Zampini 
906785d1243SStefano Zampini    Output Parameters:
907785d1243SStefano Zampini .  NeumannBoundaries - index set defining the Neumann boundaries
908785d1243SStefano Zampini 
909785d1243SStefano Zampini    Level: intermediate
910785d1243SStefano Zampini 
9110f202f7eSStefano Zampini    Notes:
9120f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetNeumannBoundaries
913785d1243SStefano Zampini 
914785d1243SStefano Zampini .seealso: PCBDDC
915785d1243SStefano Zampini @*/
916785d1243SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
917785d1243SStefano Zampini {
918785d1243SStefano Zampini   PetscErrorCode ierr;
919785d1243SStefano Zampini 
920785d1243SStefano Zampini   PetscFunctionBegin;
921785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
922785d1243SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
923785d1243SStefano Zampini   PetscFunctionReturn(0);
924785d1243SStefano Zampini }
925785d1243SStefano Zampini 
926785d1243SStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc,IS *NeumannBoundaries)
927785d1243SStefano Zampini {
928785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
929785d1243SStefano Zampini 
930785d1243SStefano Zampini   PetscFunctionBegin;
931785d1243SStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundariesLocal;
932785d1243SStefano Zampini   PetscFunctionReturn(0);
933785d1243SStefano Zampini }
934785d1243SStefano Zampini 
93553cdbc3dSStefano Zampini /*@
93682ba6b80SStefano Zampini  PCBDDCGetNeumannBoundariesLocal - Get parallel IS for Neumann boundaries (in local ordering)
93753cdbc3dSStefano Zampini 
938785d1243SStefano Zampini    Collective
93953cdbc3dSStefano Zampini 
94053cdbc3dSStefano Zampini    Input Parameters:
94128509bceSStefano Zampini .  pc - the preconditioning context
94253cdbc3dSStefano Zampini 
94353cdbc3dSStefano Zampini    Output Parameters:
94428509bceSStefano Zampini .  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
94553cdbc3dSStefano Zampini 
94653cdbc3dSStefano Zampini    Level: intermediate
94753cdbc3dSStefano Zampini 
94853cdbc3dSStefano Zampini    Notes:
9490f202f7eSStefano 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).
9500f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
95153cdbc3dSStefano Zampini 
95253cdbc3dSStefano Zampini .seealso: PCBDDC
95353cdbc3dSStefano Zampini @*/
95482ba6b80SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc,IS *NeumannBoundaries)
95553cdbc3dSStefano Zampini {
95653cdbc3dSStefano Zampini   PetscErrorCode ierr;
95753cdbc3dSStefano Zampini 
95853cdbc3dSStefano Zampini   PetscFunctionBegin;
95953cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
96082ba6b80SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundariesLocal_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
9610c7d97c5SJed Brown   PetscFunctionReturn(0);
9620c7d97c5SJed Brown }
9631e6b0712SBarry Smith 
9641a83f524SJed Brown static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
96536e030ebSStefano Zampini {
96636e030ebSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
967da1bb401SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
96856282151SStefano Zampini   PetscBool      same_data = PETSC_FALSE;
969da1bb401SStefano Zampini   PetscErrorCode ierr;
97036e030ebSStefano Zampini 
97136e030ebSStefano Zampini   PetscFunctionBegin;
9728687889aSStefano Zampini   if (!nvtxs) {
97304194a47SStefano Zampini     if (copymode == PETSC_OWN_POINTER) {
97404194a47SStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
97504194a47SStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
97604194a47SStefano Zampini     }
9778687889aSStefano Zampini     ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
9788687889aSStefano Zampini     PetscFunctionReturn(0);
9798687889aSStefano Zampini   }
98066da6bd7Sstefano_zampini   if (mat_graph->nvtxs == nvtxs && mat_graph->freecsr) { /* we own the data */
98156282151SStefano Zampini     if (mat_graph->xadj == xadj && mat_graph->adjncy == adjncy) same_data = PETSC_TRUE;
98256282151SStefano Zampini     if (!same_data && mat_graph->xadj[nvtxs] == xadj[nvtxs]) {
9832d505d7fSStefano Zampini       ierr = PetscMemcmp(xadj,mat_graph->xadj,(nvtxs+1)*sizeof(PetscInt),&same_data);CHKERRQ(ierr);
9842d505d7fSStefano Zampini       if (same_data) {
9852d505d7fSStefano Zampini         ierr = PetscMemcmp(adjncy,mat_graph->adjncy,xadj[nvtxs]*sizeof(PetscInt),&same_data);CHKERRQ(ierr);
9862d505d7fSStefano Zampini       }
98756282151SStefano Zampini     }
98856282151SStefano Zampini   }
98956282151SStefano Zampini   if (!same_data) {
990674ae819SStefano Zampini     /* free old CSR */
991674ae819SStefano Zampini     ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
992674ae819SStefano Zampini     /* get CSR into graph structure */
993da1bb401SStefano Zampini     if (copymode == PETSC_COPY_VALUES) {
994854ce69bSBarry Smith       ierr = PetscMalloc1(nvtxs+1,&mat_graph->xadj);CHKERRQ(ierr);
995785e854fSJed Brown       ierr = PetscMalloc1(xadj[nvtxs],&mat_graph->adjncy);CHKERRQ(ierr);
996674ae819SStefano Zampini       ierr = PetscMemcpy(mat_graph->xadj,xadj,(nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
997674ae819SStefano Zampini       ierr = PetscMemcpy(mat_graph->adjncy,adjncy,xadj[nvtxs]*sizeof(PetscInt));CHKERRQ(ierr);
998a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
999da1bb401SStefano Zampini     } else if (copymode == PETSC_OWN_POINTER) {
10001a83f524SJed Brown       mat_graph->xadj    = (PetscInt*)xadj;
10011a83f524SJed Brown       mat_graph->adjncy  = (PetscInt*)adjncy;
1002a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
1003a1dbd327SStefano Zampini     } else if (copymode == PETSC_USE_POINTER) {
1004a1dbd327SStefano Zampini       mat_graph->xadj    = (PetscInt*)xadj;
1005a1dbd327SStefano Zampini       mat_graph->adjncy  = (PetscInt*)adjncy;
1006a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_FALSE;
1007e0fe2d75SToby Isaac     } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %D",copymode);
1008575ad6abSStefano Zampini     mat_graph->nvtxs_csr = nvtxs;
100956282151SStefano Zampini     pcbddc->recompute_topography = PETSC_TRUE;
101056282151SStefano Zampini   }
101136e030ebSStefano Zampini   PetscFunctionReturn(0);
101236e030ebSStefano Zampini }
10131e6b0712SBarry Smith 
101436e030ebSStefano Zampini /*@
101554fffbccSStefano Zampini  PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local degrees of freedom.
101636e030ebSStefano Zampini 
101736e030ebSStefano Zampini    Not collective
101836e030ebSStefano Zampini 
101936e030ebSStefano Zampini    Input Parameters:
102054fffbccSStefano Zampini +  pc - the preconditioning context.
102154fffbccSStefano Zampini .  nvtxs - number of local vertices of the graph (i.e., the number of local dofs).
102254fffbccSStefano Zampini .  xadj, adjncy - the connectivity of the dofs in CSR format.
102354fffbccSStefano Zampini -  copymode - supported modes are PETSC_COPY_VALUES, PETSC_USE_POINTER or PETSC_OWN_POINTER.
102436e030ebSStefano Zampini 
102536e030ebSStefano Zampini    Level: intermediate
102636e030ebSStefano Zampini 
102795452b02SPatrick Sanan    Notes:
102895452b02SPatrick Sanan     A dof is considered connected with all local dofs if xadj[dof+1]-xadj[dof] == 1 and adjncy[xadj[dof]] is negative.
102936e030ebSStefano Zampini 
103028509bceSStefano Zampini .seealso: PCBDDC,PetscCopyMode
103136e030ebSStefano Zampini @*/
10321a83f524SJed Brown PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
103336e030ebSStefano Zampini {
1034575ad6abSStefano Zampini   void (*f)(void) = 0;
103536e030ebSStefano Zampini   PetscErrorCode ierr;
103636e030ebSStefano Zampini 
103736e030ebSStefano Zampini   PetscFunctionBegin;
103836e030ebSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
10398687889aSStefano Zampini   if (nvtxs) {
1040674ae819SStefano Zampini     PetscValidIntPointer(xadj,3);
10411633d1f0SStefano Zampini     if (xadj[nvtxs]) PetscValidIntPointer(adjncy,4);
10428687889aSStefano Zampini   }
10431a83f524SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
1044575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
1045575ad6abSStefano Zampini   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr);
1046575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
1047575ad6abSStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
1048575ad6abSStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
1049da1bb401SStefano Zampini   }
105036e030ebSStefano Zampini   PetscFunctionReturn(0);
105136e030ebSStefano Zampini }
10521e6b0712SBarry Smith 
105363602bcaSStefano Zampini static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
105463602bcaSStefano Zampini {
105563602bcaSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
105663602bcaSStefano Zampini   PetscInt       i;
105756282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
105863602bcaSStefano Zampini   PetscErrorCode ierr;
105963602bcaSStefano Zampini 
106063602bcaSStefano Zampini   PetscFunctionBegin;
106156282151SStefano Zampini   if (pcbddc->n_ISForDofsLocal == n_is) {
106256282151SStefano Zampini     for (i=0;i<n_is;i++) {
106356282151SStefano Zampini       PetscBool isequalt;
106456282151SStefano Zampini       ierr = ISEqual(ISForDofs[i],pcbddc->ISForDofsLocal[i],&isequalt);CHKERRQ(ierr);
106556282151SStefano Zampini       if (!isequalt) break;
106656282151SStefano Zampini     }
106756282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
106856282151SStefano Zampini   }
106956282151SStefano Zampini   for (i=0;i<n_is;i++) {
107056282151SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
107156282151SStefano Zampini   }
107263602bcaSStefano Zampini   /* Destroy ISes if they were already set */
107363602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
107463602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
107563602bcaSStefano Zampini   }
107663602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
107763602bcaSStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
107863602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
107963602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
108063602bcaSStefano Zampini   }
108163602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
108263602bcaSStefano Zampini   pcbddc->n_ISForDofs = 0;
108363602bcaSStefano Zampini   /* allocate space then set */
1084d02579f5SStefano Zampini   if (n_is) {
1085d02579f5SStefano Zampini     ierr = PetscMalloc1(n_is,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
1086d02579f5SStefano Zampini   }
108763602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
108863602bcaSStefano Zampini     pcbddc->ISForDofsLocal[i] = ISForDofs[i];
108963602bcaSStefano Zampini   }
109063602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = n_is;
109163602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
109256282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
109363602bcaSStefano Zampini   PetscFunctionReturn(0);
109463602bcaSStefano Zampini }
109563602bcaSStefano Zampini 
109663602bcaSStefano Zampini /*@
109763602bcaSStefano Zampini  PCBDDCSetDofsSplittingLocal - Set index sets defining fields of the local subdomain matrix
109863602bcaSStefano Zampini 
109963602bcaSStefano Zampini    Collective
110063602bcaSStefano Zampini 
110163602bcaSStefano Zampini    Input Parameters:
110263602bcaSStefano Zampini +  pc - the preconditioning context
11030f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
11040f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in local ordering
110563602bcaSStefano Zampini 
110663602bcaSStefano Zampini    Level: intermediate
110763602bcaSStefano Zampini 
11080f202f7eSStefano Zampini    Notes:
11090f202f7eSStefano Zampini      n_is should be the same among processes. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
111063602bcaSStefano Zampini 
111163602bcaSStefano Zampini .seealso: PCBDDC
111263602bcaSStefano Zampini @*/
111363602bcaSStefano Zampini PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc,PetscInt n_is, IS ISForDofs[])
111463602bcaSStefano Zampini {
111563602bcaSStefano Zampini   PetscInt       i;
111663602bcaSStefano Zampini   PetscErrorCode ierr;
111763602bcaSStefano Zampini 
111863602bcaSStefano Zampini   PetscFunctionBegin;
111963602bcaSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
112063602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
112163602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
112263602bcaSStefano Zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
112363602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
112463602bcaSStefano Zampini   }
1125e71e7a71SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplittingLocal_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
112663602bcaSStefano Zampini   PetscFunctionReturn(0);
112763602bcaSStefano Zampini }
112863602bcaSStefano Zampini 
11299c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
11309c0446d6SStefano Zampini {
11319c0446d6SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
11329c0446d6SStefano Zampini   PetscInt       i;
113356282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
11349c0446d6SStefano Zampini   PetscErrorCode ierr;
11359c0446d6SStefano Zampini 
11369c0446d6SStefano Zampini   PetscFunctionBegin;
113756282151SStefano Zampini   if (pcbddc->n_ISForDofs == n_is) {
113856282151SStefano Zampini     for (i=0;i<n_is;i++) {
113956282151SStefano Zampini       PetscBool isequalt;
114056282151SStefano Zampini       ierr = ISEqual(ISForDofs[i],pcbddc->ISForDofs[i],&isequalt);CHKERRQ(ierr);
114156282151SStefano Zampini       if (!isequalt) break;
114256282151SStefano Zampini     }
114356282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
114456282151SStefano Zampini   }
114556282151SStefano Zampini   for (i=0;i<n_is;i++) {
114656282151SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
114756282151SStefano Zampini   }
1148da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
11499c0446d6SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
11509c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
11519c0446d6SStefano Zampini   }
1152d11ae9bbSstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
115363602bcaSStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
115463602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
115563602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
115663602bcaSStefano Zampini   }
115763602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
115863602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = 0;
1159da1bb401SStefano Zampini   /* allocate space then set */
1160d02579f5SStefano Zampini   if (n_is) {
1161785e854fSJed Brown     ierr = PetscMalloc1(n_is,&pcbddc->ISForDofs);CHKERRQ(ierr);
1162d02579f5SStefano Zampini   }
11639c0446d6SStefano Zampini   for (i=0;i<n_is;i++) {
1164da1bb401SStefano Zampini     pcbddc->ISForDofs[i] = ISForDofs[i];
11659c0446d6SStefano Zampini   }
11669c0446d6SStefano Zampini   pcbddc->n_ISForDofs = n_is;
116763602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
116856282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
11699c0446d6SStefano Zampini   PetscFunctionReturn(0);
11709c0446d6SStefano Zampini }
11711e6b0712SBarry Smith 
11729c0446d6SStefano Zampini /*@
117363602bcaSStefano Zampini  PCBDDCSetDofsSplitting - Set index sets defining fields of the global matrix
11749c0446d6SStefano Zampini 
117563602bcaSStefano Zampini    Collective
11769c0446d6SStefano Zampini 
11779c0446d6SStefano Zampini    Input Parameters:
11789c0446d6SStefano Zampini +  pc - the preconditioning context
11790f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
11800f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in global ordering
11819c0446d6SStefano Zampini 
11829c0446d6SStefano Zampini    Level: intermediate
11839c0446d6SStefano Zampini 
11840f202f7eSStefano Zampini    Notes:
11850f202f7eSStefano Zampini      Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
11869c0446d6SStefano Zampini 
11879c0446d6SStefano Zampini .seealso: PCBDDC
11889c0446d6SStefano Zampini @*/
11899c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
11909c0446d6SStefano Zampini {
11912b510759SStefano Zampini   PetscInt       i;
11929c0446d6SStefano Zampini   PetscErrorCode ierr;
11939c0446d6SStefano Zampini 
11949c0446d6SStefano Zampini   PetscFunctionBegin;
11959c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
119663602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
11972b510759SStefano Zampini   for (i=0;i<n_is;i++) {
119863602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
1199a011d5a7Sstefano_zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
12002b510759SStefano Zampini   }
12019c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
12029c0446d6SStefano Zampini   PetscFunctionReturn(0);
12039c0446d6SStefano Zampini }
1204906d46d4SStefano Zampini 
1205534831adSStefano Zampini /*
1206534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
1207534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
12089c0446d6SStefano Zampini 
1209534831adSStefano Zampini    Input Parameter:
1210534831adSStefano Zampini +  pc - the preconditioner contex
1211534831adSStefano Zampini 
1212534831adSStefano Zampini    Application Interface Routine: PCPreSolve()
1213534831adSStefano Zampini 
1214534831adSStefano Zampini    Notes:
1215534831adSStefano Zampini      The interface routine PCPreSolve() is not usually called directly by
1216534831adSStefano Zampini    the user, but instead is called by KSPSolve().
1217534831adSStefano Zampini */
1218534831adSStefano Zampini static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1219534831adSStefano Zampini {
1220534831adSStefano Zampini   PetscErrorCode ierr;
1221534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1222534831adSStefano Zampini   PC_IS          *pcis = (PC_IS*)(pc->data);
12233972b0daSStefano Zampini   Vec            used_vec;
122427b6a85dSStefano Zampini   PetscBool      save_rhs = PETSC_TRUE, benign_correction_computed;
1225534831adSStefano Zampini 
1226534831adSStefano Zampini   PetscFunctionBegin;
12271f4df5f7SStefano Zampini   /* if we are working with CG, one dirichlet solve can be avoided during Krylov iterations */
122885c4d303SStefano Zampini   if (ksp) {
12291f4df5f7SStefano Zampini     PetscBool iscg, isgroppcg, ispipecg, ispipecgrr;
123085c4d303SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPCG,&iscg);CHKERRQ(ierr);
123127b6a85dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPGROPPCG,&isgroppcg);CHKERRQ(ierr);
123227b6a85dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECG,&ispipecg);CHKERRQ(ierr);
1233f94e96cbSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECGRR,&ispipecgrr);CHKERRQ(ierr);
12341f4df5f7SStefano Zampini     if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || (!iscg && !isgroppcg && !ispipecg && !ispipecgrr)) {
123585c4d303SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
123685c4d303SStefano Zampini     }
123785c4d303SStefano Zampini   }
1238fc17d649SStefano Zampini   if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static) {
1239fc17d649SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
1240fc17d649SStefano Zampini   }
12411f4df5f7SStefano Zampini 
124285c4d303SStefano Zampini   /* Creates parallel work vectors used in presolve */
124362a6ff1dSStefano Zampini   if (!pcbddc->original_rhs) {
124462a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
124562a6ff1dSStefano Zampini   }
124662a6ff1dSStefano Zampini   if (!pcbddc->temp_solution) {
124762a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr);
124862a6ff1dSStefano Zampini   }
12498d00608fSStefano Zampini 
125027b6a85dSStefano Zampini   pcbddc->temp_solution_used = PETSC_FALSE;
12513972b0daSStefano Zampini   if (x) {
12523972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);
12533972b0daSStefano Zampini     used_vec = x;
12548d00608fSStefano Zampini   } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */
12553972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr);
12563972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
12573972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
125827b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
1259266e20e9SStefano Zampini     ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
1260266e20e9SStefano Zampini     save_rhs = PETSC_FALSE;
1261266e20e9SStefano Zampini     pcbddc->eliminate_dirdofs = PETSC_TRUE;
12623972b0daSStefano Zampini   }
12638efcfb23SStefano Zampini 
12648efcfb23SStefano Zampini   /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */
12653972b0daSStefano Zampini   if (ksp) {
1266a0cb1b98SStefano Zampini     /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */
12678efcfb23SStefano Zampini     ierr = KSPGetInitialGuessNonzero(ksp,&pcbddc->ksp_guess_nonzero);CHKERRQ(ierr);
12688efcfb23SStefano Zampini     if (!pcbddc->ksp_guess_nonzero) {
12693972b0daSStefano Zampini       ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
12703972b0daSStefano Zampini     }
12713972b0daSStefano Zampini   }
12723308cffdSStefano Zampini 
12738d00608fSStefano Zampini   pcbddc->rhs_change = PETSC_FALSE;
12743972b0daSStefano Zampini   /* Take into account zeroed rows -> change rhs and store solution removed */
127570c64980SStefano Zampini   if (rhs && pcbddc->eliminate_dirdofs) {
12763975b054SStefano Zampini     IS dirIS = NULL;
12773975b054SStefano Zampini 
1278a07ea27aSStefano Zampini     /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */
12793975b054SStefano Zampini     ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
12803975b054SStefano Zampini     if (dirIS) {
1281906d46d4SStefano Zampini       Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
1282785d1243SStefano Zampini       PetscInt          dirsize,i,*is_indices;
12832b095fd8SStefano Zampini       PetscScalar       *array_x;
12842b095fd8SStefano Zampini       const PetscScalar *array_diagonal;
1285785d1243SStefano Zampini 
12863972b0daSStefano Zampini       ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr);
12873972b0daSStefano Zampini       ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr);
1288e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1289e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1290e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1291e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
129282ba6b80SStefano Zampini       ierr = ISGetLocalSize(dirIS,&dirsize);CHKERRQ(ierr);
12933972b0daSStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
12942b095fd8SStefano Zampini       ierr = VecGetArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
12953972b0daSStefano Zampini       ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
12962fa5cd67SKarl Rupp       for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
12973972b0daSStefano Zampini       ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
12982b095fd8SStefano Zampini       ierr = VecRestoreArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
12993972b0daSStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
1300e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1301e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13028d00608fSStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
13031b968477SStefano Zampini       ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
13048efcfb23SStefano Zampini     }
1305a07ea27aSStefano Zampini   }
1306b76ba322SStefano Zampini 
13078efcfb23SStefano Zampini   /* remove the computed solution or the initial guess from the rhs */
13088d00608fSStefano Zampini   if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero) ) {
130927b6a85dSStefano Zampini     /* save the original rhs */
131027b6a85dSStefano Zampini     if (save_rhs) {
131127b6a85dSStefano Zampini       ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
131227b6a85dSStefano Zampini       save_rhs = PETSC_FALSE;
13138d00608fSStefano Zampini     }
13148d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
13153972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
131627b6a85dSStefano Zampini     ierr = MatMultAdd(pc->mat,used_vec,pcbddc->original_rhs,rhs);CHKERRQ(ierr);
13173972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
13188efcfb23SStefano Zampini     ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr);
131927b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
13207acc28cbSStefano Zampini     if (ksp) {
13217acc28cbSStefano Zampini       ierr = KSPSetInitialGuessNonzero(ksp,PETSC_FALSE);CHKERRQ(ierr);
13227acc28cbSStefano Zampini     }
13233308cffdSStefano Zampini   }
13248efcfb23SStefano Zampini   ierr = VecDestroy(&used_vec);CHKERRQ(ierr);
1325b76ba322SStefano Zampini 
1326fc17d649SStefano Zampini   /* compute initial vector in benign space if needed
132727b6a85dSStefano Zampini      and remove non-benign solution from the rhs */
132827b6a85dSStefano Zampini   benign_correction_computed = PETSC_FALSE;
1329c69e9cc1SStefano Zampini   if (rhs && pcbddc->benign_compute_correction && (pcbddc->benign_have_null || pcbddc->benign_apply_coarse_only)) {
13301f4df5f7SStefano Zampini     /* compute u^*_h using ideas similar to those in Xuemin Tu's PhD thesis (see Section 4.8.1)
13311f4df5f7SStefano Zampini        Recursively apply BDDC in the multilevel case */
13320369aaf7SStefano Zampini     if (!pcbddc->benign_vec) {
13330369aaf7SStefano Zampini       ierr = VecDuplicate(rhs,&pcbddc->benign_vec);CHKERRQ(ierr);
13340369aaf7SStefano Zampini     }
1335c69e9cc1SStefano Zampini     /* keep applying coarse solver unless we no longer have benign subdomains */
1336c69e9cc1SStefano Zampini     pcbddc->benign_apply_coarse_only = pcbddc->benign_have_null ? PETSC_TRUE : PETSC_FALSE;
133727b6a85dSStefano Zampini     if (!pcbddc->benign_skip_correction) {
13381dd7afcfSStefano Zampini       ierr = PCApply_BDDC(pc,rhs,pcbddc->benign_vec);CHKERRQ(ierr);
13393bca92a6SStefano Zampini       benign_correction_computed = PETSC_TRUE;
13401f4df5f7SStefano Zampini       if (pcbddc->temp_solution_used) {
13411f4df5f7SStefano Zampini         ierr = VecAXPY(pcbddc->temp_solution,1.0,pcbddc->benign_vec);CHKERRQ(ierr);
13421f4df5f7SStefano Zampini       }
13431f4df5f7SStefano Zampini       ierr = VecScale(pcbddc->benign_vec,-1.0);CHKERRQ(ierr);
134427b6a85dSStefano Zampini       /* store the original rhs if not done earlier */
134527b6a85dSStefano Zampini       if (save_rhs) {
134627b6a85dSStefano Zampini         ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
134792e3dcfbSStefano Zampini       }
134827b6a85dSStefano Zampini       if (pcbddc->rhs_change) {
13490369aaf7SStefano Zampini         ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,rhs,rhs);CHKERRQ(ierr);
135027b6a85dSStefano Zampini       } else {
135127b6a85dSStefano Zampini         ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,pcbddc->original_rhs,rhs);CHKERRQ(ierr);
135227b6a85dSStefano Zampini       }
13530369aaf7SStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
135427b6a85dSStefano Zampini     }
135527b6a85dSStefano Zampini     pcbddc->benign_apply_coarse_only = PETSC_FALSE;
13560369aaf7SStefano Zampini   }
13572d4c4fecSStefano Zampini 
13582d4c4fecSStefano Zampini   /* dbg output */
1359a198735bSStefano Zampini   if (pcbddc->dbg_flag && benign_correction_computed) {
13601f4df5f7SStefano Zampini     Vec v;
1361c69e9cc1SStefano Zampini 
13621f4df5f7SStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&v);CHKERRQ(ierr);
1363c69e9cc1SStefano Zampini     if (pcbddc->ChangeOfBasisMatrix) {
13641f4df5f7SStefano Zampini       ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,v);CHKERRQ(ierr);
1365c69e9cc1SStefano Zampini     } else {
1366c69e9cc1SStefano Zampini       ierr = VecCopy(rhs,v);CHKERRQ(ierr);
1367c69e9cc1SStefano Zampini     }
13681f4df5f7SStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,v,PETSC_TRUE);CHKERRQ(ierr);
1369e0fe2d75SToby Isaac     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"LEVEL %D: is the correction benign?\n",pcbddc->current_level);CHKERRQ(ierr);
1370c69e9cc1SStefano Zampini     ierr = PetscScalarView(pcbddc->benign_n,pcbddc->benign_p0,pcbddc->dbg_viewer);CHKERRQ(ierr);
1371c69e9cc1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
13721f4df5f7SStefano Zampini     ierr = VecDestroy(&v);CHKERRQ(ierr);
13731f4df5f7SStefano Zampini   }
13740369aaf7SStefano Zampini 
13750369aaf7SStefano Zampini   /* set initial guess if using PCG */
13768ae0ca82SStefano Zampini   pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
13770369aaf7SStefano Zampini   if (x && pcbddc->use_exact_dirichlet_trick) {
13780369aaf7SStefano Zampini     ierr = VecSet(x,0.0);CHKERRQ(ierr);
13791dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
138027b6a85dSStefano Zampini       if (benign_correction_computed) { /* we have already saved the changed rhs */
13811dd7afcfSStefano Zampini         ierr = VecLockPop(pcis->vec1_global);CHKERRQ(ierr);
13821dd7afcfSStefano Zampini       } else {
13831dd7afcfSStefano Zampini         ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,pcis->vec1_global);CHKERRQ(ierr);
13841dd7afcfSStefano Zampini       }
13851dd7afcfSStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13861dd7afcfSStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13871dd7afcfSStefano Zampini     } else {
13880369aaf7SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13890369aaf7SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13901dd7afcfSStefano Zampini     }
13910369aaf7SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
13921dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
13931dd7afcfSStefano Zampini       ierr = VecSet(pcis->vec1_global,0.);CHKERRQ(ierr);
13941dd7afcfSStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13951dd7afcfSStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13961dd7afcfSStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x);CHKERRQ(ierr);
13971dd7afcfSStefano Zampini     } else {
13980369aaf7SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13990369aaf7SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
14001dd7afcfSStefano Zampini     }
14010369aaf7SStefano Zampini     if (ksp) {
14020369aaf7SStefano Zampini       ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
14030369aaf7SStefano Zampini     }
14048ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_TRUE;
1405266e20e9SStefano Zampini   } else if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior && benign_correction_computed && pcbddc->use_exact_dirichlet_trick) {
1406266e20e9SStefano Zampini     ierr = VecLockPop(pcis->vec1_global);CHKERRQ(ierr);
14070369aaf7SStefano Zampini   }
1408534831adSStefano Zampini   PetscFunctionReturn(0);
1409534831adSStefano Zampini }
1410906d46d4SStefano Zampini 
1411534831adSStefano Zampini /*
1412534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
1413534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
1414534831adSStefano Zampini 
1415534831adSStefano Zampini    Input Parameter:
1416534831adSStefano Zampini +  pc - the preconditioner contex
1417534831adSStefano Zampini 
1418534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
1419534831adSStefano Zampini 
1420534831adSStefano Zampini    Notes:
1421534831adSStefano Zampini      The interface routine PCPostSolve() is not usually called directly by
1422534831adSStefano Zampini      the user, but instead is called by KSPSolve().
1423534831adSStefano Zampini */
1424534831adSStefano Zampini static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1425534831adSStefano Zampini {
1426534831adSStefano Zampini   PetscErrorCode ierr;
1427534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1428534831adSStefano Zampini 
1429534831adSStefano Zampini   PetscFunctionBegin;
14303972b0daSStefano Zampini   /* add solution removed in presolve */
14316bcfc461SStefano Zampini   if (x && pcbddc->rhs_change) {
143227b6a85dSStefano Zampini     if (pcbddc->temp_solution_used) {
14333425bc38SStefano Zampini       ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr);
1434af140850Sstefano_zampini     } else if (pcbddc->benign_compute_correction && pcbddc->benign_vec) {
143527b6a85dSStefano Zampini       ierr = VecAXPY(x,-1.0,pcbddc->benign_vec);CHKERRQ(ierr);
14363425bc38SStefano Zampini     }
1437af140850Sstefano_zampini     /* restore to original state (not for FETI-DP) */
1438af140850Sstefano_zampini     if (ksp) pcbddc->temp_solution_used = PETSC_FALSE;
143927b6a85dSStefano Zampini   }
144027b6a85dSStefano Zampini 
1441266e20e9SStefano Zampini   /* restore rhs to its original state (not needed for FETI-DP) */
14428d00608fSStefano Zampini   if (rhs && pcbddc->rhs_change) {
144327b6a85dSStefano Zampini     ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
14448d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_FALSE;
1445af140850Sstefano_zampini   }
14468efcfb23SStefano Zampini   /* restore ksp guess state */
14478efcfb23SStefano Zampini   if (ksp) {
14488efcfb23SStefano Zampini     ierr = KSPSetInitialGuessNonzero(ksp,pcbddc->ksp_guess_nonzero);CHKERRQ(ierr);
14498ae0ca82SStefano Zampini     /* reset flag for exact dirichlet trick */
14508ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
1451af140850Sstefano_zampini   }
1452534831adSStefano Zampini   PetscFunctionReturn(0);
1453534831adSStefano Zampini }
1454af140850Sstefano_zampini 
14550c7d97c5SJed Brown /*
14560c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
14570c7d97c5SJed Brown                   by setting data structures and options.
14580c7d97c5SJed Brown 
14590c7d97c5SJed Brown    Input Parameter:
146053cdbc3dSStefano Zampini +  pc - the preconditioner context
14610c7d97c5SJed Brown 
14620c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
14630c7d97c5SJed Brown 
14640c7d97c5SJed Brown    Notes:
14650c7d97c5SJed Brown      The interface routine PCSetUp() is not usually called directly by
14660c7d97c5SJed Brown      the user, but instead is called by PCApply() if necessary.
14670c7d97c5SJed Brown */
146853cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
14690c7d97c5SJed Brown {
14700c7d97c5SJed Brown   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1471c703fcc7SStefano Zampini   PCBDDCSubSchurs sub_schurs;
14725e8657edSStefano Zampini   Mat_IS*         matis;
147308122e43SStefano Zampini   MatNullSpace    nearnullspace;
147435509ce9Sstefano_zampini   Mat             lA;
147535509ce9Sstefano_zampini   IS              lP,zerodiag = NULL;
147691e8d312SStefano Zampini   PetscInt        nrows,ncols;
147786bfa4cfSStefano Zampini   PetscMPIInt     size;
1478c703fcc7SStefano Zampini   PetscBool       computesubschurs;
14798de1fae6SStefano Zampini   PetscBool       computeconstraintsmatrix;
14805e8657edSStefano Zampini   PetscBool       new_nearnullspace_provided,ismatis;
1481c703fcc7SStefano Zampini   PetscErrorCode  ierr;
14820c7d97c5SJed Brown 
14830c7d97c5SJed Brown   PetscFunctionBegin;
14845e8657edSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATIS,&ismatis);CHKERRQ(ierr);
14856c4ed002SBarry Smith   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner requires matrix of type MATIS");
148691e8d312SStefano Zampini   ierr = MatGetSize(pc->pmat,&nrows,&ncols);CHKERRQ(ierr);
14876c4ed002SBarry Smith   if (nrows != ncols) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCBDDC preconditioner requires a square preconditioning matrix");
148886bfa4cfSStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
148986bfa4cfSStefano Zampini 
14905e8657edSStefano Zampini   matis = (Mat_IS*)pc->pmat->data;
1491f4ddd8eeSStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */
14923b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
149371582508SStefano Zampini      Also, BDDC builds its own KSP for the Dirichlet problem */
1494a485753aSstefano_zampini   if (!pc->setupcalled || pc->flag == DIFFERENT_NONZERO_PATTERN) pcbddc->recompute_topography = PETSC_TRUE;
1495c83e1ba7SStefano Zampini   if (pcbddc->recompute_topography) {
1496c83e1ba7SStefano Zampini     pcbddc->graphanalyzed    = PETSC_FALSE;
1497c83e1ba7SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1498c83e1ba7SStefano Zampini   } else {
14998de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_FALSE;
1500c83e1ba7SStefano Zampini   }
1501b087196eSStefano Zampini 
1502b087196eSStefano Zampini   /* check parameters' compatibility */
1503b7ab4a40SStefano Zampini   if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE;
1504bd2a564bSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_threshold[0] != 0.0 || pcbddc->adaptive_threshold[1] != 0.0);
150586bfa4cfSStefano Zampini   pcbddc->use_deluxe_scaling   = (PetscBool)(pcbddc->use_deluxe_scaling && size > 1);
150686bfa4cfSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_selection && size > 1);
1507bf3a8328SStefano Zampini   pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined);
1508862806e4SStefano Zampini   if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE;
1509862806e4SStefano Zampini 
15105a95e1ceSStefano Zampini   computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling);
151116909a7fSStefano Zampini   if (pcbddc->switch_static) {
151216909a7fSStefano Zampini     PetscBool ismatis;
1513d9869140SStefano Zampini 
151416909a7fSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc->mat,MATIS,&ismatis);CHKERRQ(ierr);
151516909a7fSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"When the static switch is one, the iteration matrix should be of type MATIS");
151616909a7fSStefano Zampini   }
151716909a7fSStefano Zampini 
151871582508SStefano Zampini   /* activate all connected components if the netflux has been requested */
1519bb05f991SStefano Zampini   if (pcbddc->compute_nonetflux) {
1520bb05f991SStefano Zampini     pcbddc->use_vertices = PETSC_TRUE;
1521bb05f991SStefano Zampini     pcbddc->use_edges    = PETSC_TRUE;
1522bb05f991SStefano Zampini     pcbddc->use_faces    = PETSC_TRUE;
1523bb05f991SStefano Zampini   }
1524bb05f991SStefano Zampini 
1525f4ddd8eeSStefano Zampini   /* Get stdout for dbg */
152670cf5478SStefano Zampini   if (pcbddc->dbg_flag) {
152770cf5478SStefano Zampini     if (!pcbddc->dbg_viewer) {
152858a03d70SStefano Zampini       pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc));
1529f4ddd8eeSStefano Zampini     }
1530d9869140SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
153158a03d70SStefano Zampini     ierr = PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
1532f4ddd8eeSStefano Zampini   }
1533f4ddd8eeSStefano Zampini 
1534c703fcc7SStefano Zampini   /* process topology information */
153543371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_Topology[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
153671582508SStefano Zampini   if (pcbddc->recompute_topography) {
153771582508SStefano Zampini     ierr = PCBDDCComputeLocalTopologyInfo(pc);CHKERRQ(ierr);
1538c703fcc7SStefano Zampini     if (pcbddc->discretegradient) {
1539a13144ffSStefano Zampini       ierr = PCBDDCNedelecSupport(pc);CHKERRQ(ierr);
1540a13144ffSStefano Zampini     }
1541c703fcc7SStefano Zampini   }
1542a13144ffSStefano Zampini 
1543c703fcc7SStefano Zampini   /* change basis if requested by the user */
15445e8657edSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) {
15455e8657edSStefano Zampini     /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */
15465e8657edSStefano Zampini     pcbddc->use_change_of_basis = PETSC_FALSE;
15475e8657edSStefano Zampini     ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
15485e8657edSStefano Zampini   } else {
1549b96c3477SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
15505e8657edSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
15515e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
1552d16cbb6bSStefano Zampini   }
1553d16cbb6bSStefano Zampini 
15544f1b2e48SStefano Zampini   /*
1555c703fcc7SStefano Zampini      Compute change of basis on local pressures (aka zerodiag dofs) with the benign trick
15564f1b2e48SStefano Zampini      This should come earlier then PCISSetUp for extracting the correct subdomain matrices
15574f1b2e48SStefano Zampini   */
15581dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
1559d16cbb6bSStefano Zampini   if (pcbddc->benign_saddle_point) {
15609f47a83aSStefano Zampini     PC_IS* pcis = (PC_IS*)pc->data;
15619f47a83aSStefano Zampini 
156205b28244SStefano Zampini     if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE;
1563669cc0f4SStefano Zampini     /* detect local saddle point and change the basis in pcbddc->local_mat (TODO: reuse case) */
1564339f8db1SStefano Zampini     ierr = PCBDDCBenignDetectSaddlePoint(pc,&zerodiag);CHKERRQ(ierr);
1565a3df083aSStefano Zampini     /* pop B0 mat from local mat */
1566c263805aSStefano Zampini     ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
15671dd7afcfSStefano Zampini     /* give pcis a hint to not reuse submatrices during PCISCreate */
15681dd7afcfSStefano Zampini     if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) {
15691dd7afcfSStefano Zampini       if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) {
15701dd7afcfSStefano Zampini         pcis->reusesubmatrices = PETSC_FALSE;
15711dd7afcfSStefano Zampini       } else {
1572a3df083aSStefano Zampini         pcis->reusesubmatrices = PETSC_TRUE;
15731dd7afcfSStefano Zampini       }
1574a3df083aSStefano Zampini     } else {
15759f47a83aSStefano Zampini       pcis->reusesubmatrices = PETSC_FALSE;
1576674ae819SStefano Zampini     }
1577a3df083aSStefano Zampini   }
157827b6a85dSStefano Zampini 
15798037d520SStefano Zampini   /* propagate relevant information */
158006a4e24aSStefano Zampini   if (matis->A->symmetric_set) {
158106a4e24aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
158206a4e24aSStefano Zampini   }
158306a4e24aSStefano Zampini   if (matis->A->spd_set) {
158406a4e24aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SPD,matis->A->spd);CHKERRQ(ierr);
158506a4e24aSStefano Zampini   }
1586e496cd5dSStefano Zampini 
15875e8657edSStefano Zampini   /* Set up all the "iterative substructuring" common block without computing solvers */
15885e8657edSStefano Zampini   {
15895e8657edSStefano Zampini     Mat temp_mat;
15905e8657edSStefano Zampini 
15915e8657edSStefano Zampini     temp_mat = matis->A;
15925e8657edSStefano Zampini     matis->A = pcbddc->local_mat;
1593d9869140SStefano Zampini     ierr = PCISSetUp(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
15945e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
15955e8657edSStefano Zampini     matis->A = temp_mat;
15965e8657edSStefano Zampini   }
1597684f6988SStefano Zampini 
159881d14e9dSStefano Zampini   /* Analyze interface */
159964ac59b8SStefano Zampini   if (!pcbddc->graphanalyzed) {
1600674ae819SStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
16018de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1602345ecf6cSStefano Zampini     if (pcbddc->adaptive_selection && !pcbddc->use_deluxe_scaling && !pcbddc->mat_graph->twodim) {
16034247aa23Sstefano_zampini       SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot compute the adaptive primal space for a problem with 3D edges without deluxe scaling");
1604345ecf6cSStefano Zampini     }
1605a198735bSStefano Zampini     if (pcbddc->compute_nonetflux) {
1606669cc0f4SStefano Zampini       MatNullSpace nnfnnsp;
1607669cc0f4SStefano Zampini 
160821ef3d20SStefano Zampini       if (!pcbddc->divudotp) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Missing divudotp operator");
16098ae0ca82SStefano Zampini       ierr = PCBDDCComputeNoNetFlux(pc->pmat,pcbddc->divudotp,pcbddc->divudotp_trans,pcbddc->divudotp_vl2l,pcbddc->mat_graph,&nnfnnsp);CHKERRQ(ierr);
161071582508SStefano Zampini       /* TODO what if a nearnullspace is already attached? */
16118037d520SStefano Zampini       if (nnfnnsp) {
1612669cc0f4SStefano Zampini         ierr = MatSetNearNullSpace(pc->pmat,nnfnnsp);CHKERRQ(ierr);
1613669cc0f4SStefano Zampini         ierr = MatNullSpaceDestroy(&nnfnnsp);CHKERRQ(ierr);
1614669cc0f4SStefano Zampini       }
1615674ae819SStefano Zampini     }
16168037d520SStefano Zampini   }
161743371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_Topology[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
1618fb8d54d4SStefano Zampini 
16195408967cSStefano Zampini   /* check existence of a divergence free extension, i.e.
16205408967cSStefano Zampini      b(v_I,p_0) = 0 for all v_I (raise error if not).
16215408967cSStefano Zampini      Also, check that PCBDDCBenignGetOrSetP0 works */
1622ff1f7e73Sstefano_zampini   if (pcbddc->benign_saddle_point && pcbddc->dbg_flag > 1) {
16235408967cSStefano Zampini     ierr = PCBDDCBenignCheck(pc,zerodiag);CHKERRQ(ierr);
162409f581a4SStefano Zampini   }
16254f1b2e48SStefano Zampini   ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
162606f24817SStefano Zampini 
1627b96c3477SStefano Zampini   /* Setup local dirichlet solver ksp_D and sub_schurs solvers */
1628c703fcc7SStefano Zampini   if (computesubschurs && pcbddc->recompute_topography) {
162908122e43SStefano Zampini     ierr = PCBDDCInitSubSchurs(pc);CHKERRQ(ierr);
1630b1b3d7a2SStefano Zampini   }
16319d54b7f4SStefano Zampini   /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/
16329d54b7f4SStefano Zampini   if (!pcbddc->use_deluxe_scaling) {
16339d54b7f4SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
16349d54b7f4SStefano Zampini   }
1635c703fcc7SStefano Zampini 
1636c703fcc7SStefano Zampini   /* finish setup solvers and do adaptive selection of constraints */
1637b334f244SStefano Zampini   sub_schurs = pcbddc->sub_schurs;
1638b334f244SStefano Zampini   if (sub_schurs && sub_schurs->schur_explicit) {
16392070dbb6SStefano Zampini     if (computesubschurs) {
164008122e43SStefano Zampini       ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
16412070dbb6SStefano Zampini     }
1642d5574798SStefano Zampini     ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
1643d5574798SStefano Zampini   } else {
1644d5574798SStefano Zampini     ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
16452070dbb6SStefano Zampini     if (computesubschurs) {
1646d5574798SStefano Zampini       ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
1647d5574798SStefano Zampini     }
16482070dbb6SStefano Zampini   }
164908122e43SStefano Zampini   if (pcbddc->adaptive_selection) {
165008122e43SStefano Zampini     ierr = PCBDDCAdaptiveSelection(pc);CHKERRQ(ierr);
16518de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1652b7eb3628SStefano Zampini   }
1653684f6988SStefano Zampini 
1654f4ddd8eeSStefano Zampini   /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */
1655fb8d54d4SStefano Zampini   new_nearnullspace_provided = PETSC_FALSE;
1656f4ddd8eeSStefano Zampini   ierr = MatGetNearNullSpace(pc->pmat,&nearnullspace);CHKERRQ(ierr);
1657f4ddd8eeSStefano Zampini   if (pcbddc->onearnullspace) { /* already used nearnullspace */
1658f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* near null space attached to mat has been destroyed */
1659f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1660f4ddd8eeSStefano Zampini     } else {
1661f4ddd8eeSStefano Zampini       /* determine if the two nullspaces are different (should be lightweight) */
1662f4ddd8eeSStefano Zampini       if (nearnullspace != pcbddc->onearnullspace) {
1663f4ddd8eeSStefano Zampini         new_nearnullspace_provided = PETSC_TRUE;
1664165b64e2SStefano Zampini       } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */
1665f4ddd8eeSStefano Zampini         PetscInt         i;
1666165b64e2SStefano Zampini         const Vec        *nearnullvecs;
1667165b64e2SStefano Zampini         PetscObjectState state;
1668165b64e2SStefano Zampini         PetscInt         nnsp_size;
1669165b64e2SStefano Zampini         ierr = MatNullSpaceGetVecs(nearnullspace,NULL,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
1670f4ddd8eeSStefano Zampini         for (i=0;i<nnsp_size;i++) {
1671f4ddd8eeSStefano Zampini           ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&state);CHKERRQ(ierr);
1672165b64e2SStefano Zampini           if (pcbddc->onearnullvecs_state[i] != state) {
1673f4ddd8eeSStefano Zampini             new_nearnullspace_provided = PETSC_TRUE;
1674f4ddd8eeSStefano Zampini             break;
1675f4ddd8eeSStefano Zampini           }
1676f4ddd8eeSStefano Zampini         }
1677f4ddd8eeSStefano Zampini       }
1678f4ddd8eeSStefano Zampini     }
1679f4ddd8eeSStefano Zampini   } else {
1680f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* both nearnullspaces are null */
1681f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_FALSE;
1682f4ddd8eeSStefano Zampini     } else { /* nearnullspace attached later */
1683f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1684f4ddd8eeSStefano Zampini     }
1685f4ddd8eeSStefano Zampini   }
1686f4ddd8eeSStefano Zampini 
1687f4ddd8eeSStefano Zampini   /* Setup constraints and related work vectors */
1688727cdba6SStefano Zampini   /* reset primal space flags */
168943371fb9SStefano Zampini   ierr = PetscLogEventBegin(PC_BDDC_LocalWork[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
1690f4ddd8eeSStefano Zampini   pcbddc->new_primal_space = PETSC_FALSE;
1691727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_FALSE;
16928de1fae6SStefano Zampini   if (computeconstraintsmatrix || new_nearnullspace_provided) {
1693727cdba6SStefano Zampini     /* It also sets the primal space flags */
1694674ae819SStefano Zampini     ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr);
16959543d0ffSStefano Zampini   }
1696e7b262bdSStefano Zampini   /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */
1697f4ddd8eeSStefano Zampini   ierr = PCBDDCSetUpLocalWorkVectors(pc);CHKERRQ(ierr);
16985e8657edSStefano Zampini 
16995e8657edSStefano Zampini   if (pcbddc->use_change_of_basis) {
17005e8657edSStefano Zampini     PC_IS *pcis = (PC_IS*)(pc->data);
17015e8657edSStefano Zampini 
17025e8657edSStefano Zampini     ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
17034f1b2e48SStefano Zampini     if (pcbddc->benign_change) {
17041dd7afcfSStefano Zampini       ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
1705c263805aSStefano Zampini       /* pop B0 from pcbddc->local_mat */
1706c263805aSStefano Zampini       ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
1707c263805aSStefano Zampini     }
17085e8657edSStefano Zampini     /* get submatrices */
17095e8657edSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
17105e8657edSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
17115e8657edSStefano Zampini     ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);
17127dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB);CHKERRQ(ierr);
17137dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr);
17147dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr);
17153975b054SStefano Zampini     /* set flag in pcis to not reuse submatrices during PCISCreate */
17163975b054SStefano Zampini     pcis->reusesubmatrices = PETSC_FALSE;
17179c6a02ceSStefano Zampini   } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) {
1718b96c3477SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
17195e8657edSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
17205e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
17215e8657edSStefano Zampini   }
172235509ce9Sstefano_zampini 
172335509ce9Sstefano_zampini   /* interface pressure block row for B_C */
172435509ce9Sstefano_zampini   ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP" ,(PetscObject*)&lP);CHKERRQ(ierr);
172535509ce9Sstefano_zampini   ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA);CHKERRQ(ierr);
172635509ce9Sstefano_zampini   if (lA && lP) {
172735509ce9Sstefano_zampini     PC_IS*    pcis = (PC_IS*)pc->data;
172835509ce9Sstefano_zampini     Mat       B_BI,B_BB,Bt_BI,Bt_BB;
172935509ce9Sstefano_zampini     PetscBool issym;
173035509ce9Sstefano_zampini     ierr = MatIsSymmetric(lA,PETSC_SMALL,&issym);CHKERRQ(ierr);
17316cc1294bSstefano_zampini     if (issym) {
17327dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI);CHKERRQ(ierr);
17337dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB);CHKERRQ(ierr);
173435509ce9Sstefano_zampini       ierr = MatCreateTranspose(B_BI,&Bt_BI);CHKERRQ(ierr);
173535509ce9Sstefano_zampini       ierr = MatCreateTranspose(B_BB,&Bt_BB);CHKERRQ(ierr);
173635509ce9Sstefano_zampini     } else {
17377dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI);CHKERRQ(ierr);
17387dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB);CHKERRQ(ierr);
17397dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,pcis->is_I_local,lP,MAT_INITIAL_MATRIX,&Bt_BI);CHKERRQ(ierr);
17407dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,pcis->is_B_local,lP,MAT_INITIAL_MATRIX,&Bt_BB);CHKERRQ(ierr);
174135509ce9Sstefano_zampini     }
174235509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BI",(PetscObject)B_BI);CHKERRQ(ierr);
174335509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BB",(PetscObject)B_BB);CHKERRQ(ierr);
174435509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BI",(PetscObject)Bt_BI);CHKERRQ(ierr);
174535509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BB",(PetscObject)Bt_BB);CHKERRQ(ierr);
174635509ce9Sstefano_zampini     ierr = MatDestroy(&B_BI);CHKERRQ(ierr);
174735509ce9Sstefano_zampini     ierr = MatDestroy(&B_BB);CHKERRQ(ierr);
174835509ce9Sstefano_zampini     ierr = MatDestroy(&Bt_BI);CHKERRQ(ierr);
174935509ce9Sstefano_zampini     ierr = MatDestroy(&Bt_BB);CHKERRQ(ierr);
175035509ce9Sstefano_zampini   }
175143371fb9SStefano Zampini   ierr = PetscLogEventEnd(PC_BDDC_LocalWork[pcbddc->current_level],pc,0,0,0);CHKERRQ(ierr);
175235509ce9Sstefano_zampini 
1753b96c3477SStefano Zampini   /* SetUp coarse and local Neumann solvers */
175499cc7994SStefano Zampini   ierr = PCBDDCSetUpSolvers(pc);CHKERRQ(ierr);
1755b96c3477SStefano Zampini   /* SetUp Scaling operator */
17569d54b7f4SStefano Zampini   if (pcbddc->use_deluxe_scaling) {
1757674ae819SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
17580c7d97c5SJed Brown   }
1759c703fcc7SStefano Zampini 
17601dd7afcfSStefano Zampini   /* mark topography as done */
176156282151SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
17620369aaf7SStefano Zampini 
17631dd7afcfSStefano Zampini   /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */
17641dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_FALSE);CHKERRQ(ierr);
17651dd7afcfSStefano Zampini 
176658a03d70SStefano Zampini   if (pcbddc->dbg_flag) {
176758a03d70SStefano Zampini     ierr = PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
1768d9869140SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
17692b510759SStefano Zampini   }
17700c7d97c5SJed Brown   PetscFunctionReturn(0);
17710c7d97c5SJed Brown }
17720c7d97c5SJed Brown 
17730c7d97c5SJed Brown /*
177450efa1b5SStefano Zampini    PCApply_BDDC - Applies the BDDC operator to a vector.
17750c7d97c5SJed Brown 
17760c7d97c5SJed Brown    Input Parameters:
17770f202f7eSStefano Zampini +  pc - the preconditioner context
17780f202f7eSStefano Zampini -  r - input vector (global)
17790c7d97c5SJed Brown 
17800c7d97c5SJed Brown    Output Parameter:
17810c7d97c5SJed Brown .  z - output vector (global)
17820c7d97c5SJed Brown 
17830c7d97c5SJed Brown    Application Interface Routine: PCApply()
17840c7d97c5SJed Brown  */
178553cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
17860c7d97c5SJed Brown {
17870c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
17880c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1789b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
17900c7d97c5SJed Brown   PetscErrorCode    ierr;
17913b03a366Sstefano_zampini   const PetscScalar one = 1.0;
17923b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
17932617d88aSStefano Zampini   const PetscScalar zero = 0.0;
17940c7d97c5SJed Brown 
17950c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
17960c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
1797b097fa66SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */
17980c7d97c5SJed Brown 
17990c7d97c5SJed Brown   PetscFunctionBegin;
1800f3d41395Sstefano_zampini   ierr = PetscCitationsRegister(citation,&cited);CHKERRQ(ierr);
18011dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
18021dd7afcfSStefano Zampini     Vec swap;
180327b6a85dSStefano Zampini 
180427b6a85dSStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
18051dd7afcfSStefano Zampini     swap = pcbddc->work_change;
18061dd7afcfSStefano Zampini     pcbddc->work_change = r;
18071dd7afcfSStefano Zampini     r = swap;
18081dd7afcfSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
18099cc2a9b1Sstefano_zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) {
18101dd7afcfSStefano Zampini       ierr = VecCopy(r,pcis->vec1_global);CHKERRQ(ierr);
18111dd7afcfSStefano Zampini       ierr = VecLockPush(pcis->vec1_global);CHKERRQ(ierr);
18121dd7afcfSStefano Zampini     }
18131dd7afcfSStefano Zampini   }
181427b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
1815015636ebSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
1816efc2fbd9SStefano Zampini   }
18178ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1818b097fa66SStefano Zampini     ierr = VecCopy(r,z);CHKERRQ(ierr);
18190c7d97c5SJed Brown     /* First Dirichlet solve */
18200c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18210c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18220c7d97c5SJed Brown     /*
18230c7d97c5SJed Brown       Assembling right hand side for BDDC operator
1824b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
1825674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
18260c7d97c5SJed Brown     */
1827b097fa66SStefano Zampini     if (n_D) {
1828b097fa66SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
18290c7d97c5SJed Brown       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
183016909a7fSStefano Zampini       if (pcbddc->switch_static) {
183116909a7fSStefano Zampini         Mat_IS *matis = (Mat_IS*)(pc->mat->data);
183216909a7fSStefano Zampini 
183316909a7fSStefano Zampini         ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
183416909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
183516909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
183616909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
183716909a7fSStefano Zampini           ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
183816909a7fSStefano Zampini         } else {
183916909a7fSStefano Zampini           ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
184016909a7fSStefano Zampini           ierr = MatMult(matis->A,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
184116909a7fSStefano Zampini           ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
184216909a7fSStefano Zampini         }
184316909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
184416909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
184516909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
184616909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
184716909a7fSStefano Zampini       } else {
1848b097fa66SStefano Zampini         ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
184916909a7fSStefano Zampini       }
1850b097fa66SStefano Zampini     } else {
1851b097fa66SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1852b097fa66SStefano Zampini     }
18530c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
18540c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1855674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
1856b76ba322SStefano Zampini   } else {
18574fee134fSStefano Zampini     if (!pcbddc->benign_apply_coarse_only) {
1858674ae819SStefano Zampini       ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
1859b76ba322SStefano Zampini     }
18604fee134fSStefano Zampini   }
1861b76ba322SStefano Zampini 
18622617d88aSStefano Zampini   /* Apply interface preconditioner
18632617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
1864dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
18652617d88aSStefano Zampini 
1866674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
1867674ae819SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
18680c7d97c5SJed Brown 
18693b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
18700c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18710c7d97c5SJed Brown   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1872b097fa66SStefano Zampini   if (n_B) {
187316909a7fSStefano Zampini     if (pcbddc->switch_static) {
187416909a7fSStefano Zampini       Mat_IS *matis = (Mat_IS*)(pc->mat->data);
187516909a7fSStefano Zampini 
187616909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
187716909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
187816909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
187916909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
188016909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
188116909a7fSStefano Zampini         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
188216909a7fSStefano Zampini       } else {
188316909a7fSStefano Zampini         ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
188416909a7fSStefano Zampini         ierr = MatMult(matis->A,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
188516909a7fSStefano Zampini         ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
188616909a7fSStefano Zampini       }
188716909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
188816909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
188916909a7fSStefano Zampini     } else {
18900c7d97c5SJed Brown       ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
189116909a7fSStefano Zampini     }
189216909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
189316909a7fSStefano Zampini     Mat_IS *matis = (Mat_IS*)(pc->mat->data);
189416909a7fSStefano Zampini 
189516909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
189616909a7fSStefano Zampini       ierr = MatMult(matis->A,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
189716909a7fSStefano Zampini     } else {
189816909a7fSStefano Zampini       ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N);CHKERRQ(ierr);
189916909a7fSStefano Zampini       ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
190016909a7fSStefano Zampini       ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D);CHKERRQ(ierr);
190116909a7fSStefano Zampini     }
1902b097fa66SStefano Zampini   }
1903df187020SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
1904efc2fbd9SStefano Zampini 
19058ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1906b097fa66SStefano Zampini     if (pcbddc->switch_static) {
1907b097fa66SStefano Zampini       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
1908b097fa66SStefano Zampini     } else {
1909b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
1910b097fa66SStefano Zampini     }
19110c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
19120c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1913b097fa66SStefano Zampini   } else {
1914b097fa66SStefano Zampini     if (pcbddc->switch_static) {
1915b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
1916b097fa66SStefano Zampini     } else {
1917b097fa66SStefano Zampini       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
1918b097fa66SStefano Zampini     }
1919b097fa66SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1920b097fa66SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1921b097fa66SStefano Zampini   }
192227b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
19231dd7afcfSStefano Zampini     if (pcbddc->benign_apply_coarse_only) {
19241dd7afcfSStefano Zampini       ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
19251dd7afcfSStefano Zampini     }
1926015636ebSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
1927efc2fbd9SStefano Zampini   }
19281f4df5f7SStefano Zampini 
19291dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1930f913dca9SStefano Zampini     pcbddc->work_change = r;
19311dd7afcfSStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
19321dd7afcfSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
19331dd7afcfSStefano Zampini   }
19340c7d97c5SJed Brown   PetscFunctionReturn(0);
19350c7d97c5SJed Brown }
193650efa1b5SStefano Zampini 
193750efa1b5SStefano Zampini /*
193850efa1b5SStefano Zampini    PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector.
193950efa1b5SStefano Zampini 
194050efa1b5SStefano Zampini    Input Parameters:
19410f202f7eSStefano Zampini +  pc - the preconditioner context
19420f202f7eSStefano Zampini -  r - input vector (global)
194350efa1b5SStefano Zampini 
194450efa1b5SStefano Zampini    Output Parameter:
194550efa1b5SStefano Zampini .  z - output vector (global)
194650efa1b5SStefano Zampini 
194750efa1b5SStefano Zampini    Application Interface Routine: PCApplyTranspose()
194850efa1b5SStefano Zampini  */
194950efa1b5SStefano Zampini PetscErrorCode PCApplyTranspose_BDDC(PC pc,Vec r,Vec z)
195050efa1b5SStefano Zampini {
195150efa1b5SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
195250efa1b5SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1953b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
195450efa1b5SStefano Zampini   PetscErrorCode    ierr;
195550efa1b5SStefano Zampini   const PetscScalar one = 1.0;
195650efa1b5SStefano Zampini   const PetscScalar m_one = -1.0;
195750efa1b5SStefano Zampini   const PetscScalar zero = 0.0;
195850efa1b5SStefano Zampini 
195950efa1b5SStefano Zampini   PetscFunctionBegin;
1960f3d41395Sstefano_zampini   ierr = PetscCitationsRegister(citation,&cited);CHKERRQ(ierr);
19611dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
19621dd7afcfSStefano Zampini     Vec swap;
196327b6a85dSStefano Zampini 
196427b6a85dSStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
19651dd7afcfSStefano Zampini     swap = pcbddc->work_change;
19661dd7afcfSStefano Zampini     pcbddc->work_change = r;
19671dd7afcfSStefano Zampini     r = swap;
196827b6a85dSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
19698ae0ca82SStefano Zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->exact_dirichlet_trick_app && pcbddc->change_interior) {
197027b6a85dSStefano Zampini       ierr = VecCopy(r,pcis->vec1_global);CHKERRQ(ierr);
197127b6a85dSStefano Zampini       ierr = VecLockPush(pcis->vec1_global);CHKERRQ(ierr);
19721dd7afcfSStefano Zampini     }
197327b6a85dSStefano Zampini   }
197427b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
1975537c1cdfSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
1976537c1cdfSStefano Zampini   }
19778ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1978b097fa66SStefano Zampini     ierr = VecCopy(r,z);CHKERRQ(ierr);
197950efa1b5SStefano Zampini     /* First Dirichlet solve */
198050efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
198150efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
198250efa1b5SStefano Zampini     /*
198350efa1b5SStefano Zampini       Assembling right hand side for BDDC operator
1984b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
198550efa1b5SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
198650efa1b5SStefano Zampini     */
1987b097fa66SStefano Zampini     if (n_D) {
1988b097fa66SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
198950efa1b5SStefano Zampini       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
199016909a7fSStefano Zampini       if (pcbddc->switch_static) {
199116909a7fSStefano Zampini         Mat_IS *matis = (Mat_IS*)(pc->mat->data);
199216909a7fSStefano Zampini 
199316909a7fSStefano Zampini         ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
199416909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
199516909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
199616909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
199716909a7fSStefano Zampini           ierr = MatMultTranspose(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
199816909a7fSStefano Zampini         } else {
199916909a7fSStefano Zampini           ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
200016909a7fSStefano Zampini           ierr = MatMultTranspose(matis->A,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
200116909a7fSStefano Zampini           ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
200216909a7fSStefano Zampini         }
200316909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
200416909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
200516909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
200616909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
200716909a7fSStefano Zampini       } else {
2008b097fa66SStefano Zampini         ierr = MatMultTranspose(pcis->A_IB,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
200916909a7fSStefano Zampini       }
2010b097fa66SStefano Zampini     } else {
2011b097fa66SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
2012b097fa66SStefano Zampini     }
201350efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
201450efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
201550efa1b5SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
201650efa1b5SStefano Zampini   } else {
201750efa1b5SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
201850efa1b5SStefano Zampini   }
201950efa1b5SStefano Zampini 
202050efa1b5SStefano Zampini   /* Apply interface preconditioner
202150efa1b5SStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
2022dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_TRUE);CHKERRQ(ierr);
202350efa1b5SStefano Zampini 
202450efa1b5SStefano Zampini   /* Apply transpose of partition of unity operator */
202550efa1b5SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
202650efa1b5SStefano Zampini 
202750efa1b5SStefano Zampini   /* Second Dirichlet solve and assembling of output */
202850efa1b5SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
202950efa1b5SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2030b097fa66SStefano Zampini   if (n_B) {
203116909a7fSStefano Zampini     if (pcbddc->switch_static) {
203216909a7fSStefano Zampini       Mat_IS *matis = (Mat_IS*)(pc->mat->data);
203316909a7fSStefano Zampini 
203416909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
203516909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
203616909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
203716909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
203816909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
203916909a7fSStefano Zampini         ierr = MatMultTranspose(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
204016909a7fSStefano Zampini       } else {
204116909a7fSStefano Zampini         ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
204216909a7fSStefano Zampini         ierr = MatMultTranspose(matis->A,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
204316909a7fSStefano Zampini         ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
204416909a7fSStefano Zampini       }
204516909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
204616909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
204716909a7fSStefano Zampini     } else {
204850efa1b5SStefano Zampini       ierr = MatMultTranspose(pcis->A_BI,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
204916909a7fSStefano Zampini     }
205016909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
205116909a7fSStefano Zampini     Mat_IS *matis = (Mat_IS*)(pc->mat->data);
205216909a7fSStefano Zampini 
205316909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
205416909a7fSStefano Zampini       ierr = MatMultTranspose(matis->A,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
205516909a7fSStefano Zampini     } else {
205616909a7fSStefano Zampini       ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N);CHKERRQ(ierr);
205716909a7fSStefano Zampini       ierr = MatMultTranspose(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
205816909a7fSStefano Zampini       ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D);CHKERRQ(ierr);
205916909a7fSStefano Zampini     }
2060b097fa66SStefano Zampini   }
2061b0147a47SStefano Zampini   ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
20628ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
2063b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2064b097fa66SStefano Zampini       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
2065b097fa66SStefano Zampini     } else {
2066b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
2067b097fa66SStefano Zampini     }
206850efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
206950efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2070b097fa66SStefano Zampini   } else {
2071b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2072b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
2073b097fa66SStefano Zampini     } else {
2074b097fa66SStefano Zampini       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
2075b097fa66SStefano Zampini     }
2076b097fa66SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2077b097fa66SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2078b097fa66SStefano Zampini   }
207927b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
2080537c1cdfSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
2081537c1cdfSStefano Zampini   }
20821dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2083f913dca9SStefano Zampini     pcbddc->work_change = r;
20841dd7afcfSStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
20851dd7afcfSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
20861dd7afcfSStefano Zampini   }
208750efa1b5SStefano Zampini   PetscFunctionReturn(0);
208850efa1b5SStefano Zampini }
2089674ae819SStefano Zampini 
20909326c5c6Sstefano_zampini PetscErrorCode PCReset_BDDC(PC pc)
2091da1bb401SStefano Zampini {
2092da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
20939326c5c6Sstefano_zampini   PC_IS          *pcis = (PC_IS*)pc->data;
20949326c5c6Sstefano_zampini   KSP            kspD,kspR,kspC;
2095da1bb401SStefano Zampini   PetscErrorCode ierr;
2096da1bb401SStefano Zampini 
2097da1bb401SStefano Zampini   PetscFunctionBegin;
2098674ae819SStefano Zampini   /* free BDDC custom data  */
2099674ae819SStefano Zampini   ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr);
2100674ae819SStefano Zampini   /* destroy objects related to topography */
2101674ae819SStefano Zampini   ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
210234a97f8cSStefano Zampini   /* destroy objects for scaling operator */
2103674ae819SStefano Zampini   ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
2104674ae819SStefano Zampini   /* free solvers stuff */
2105674ae819SStefano Zampini   ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
210662a6ff1dSStefano Zampini   /* free global vectors needed in presolve */
210762a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr);
210862a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr);
21091dd7afcfSStefano Zampini   /* free data created by PCIS */
21101dd7afcfSStefano Zampini   ierr = PCISDestroy(pc);CHKERRQ(ierr);
21119326c5c6Sstefano_zampini 
21129326c5c6Sstefano_zampini   /* restore defaults */
21139326c5c6Sstefano_zampini   kspD = pcbddc->ksp_D;
21149326c5c6Sstefano_zampini   kspR = pcbddc->ksp_R;
21159326c5c6Sstefano_zampini   kspC = pcbddc->coarse_ksp;
21169326c5c6Sstefano_zampini   ierr = PetscMemzero(pc->data,sizeof(*pcbddc));CHKERRQ(ierr);
21179326c5c6Sstefano_zampini   pcis->n_neigh                     = -1;
21189326c5c6Sstefano_zampini   pcis->scaling_factor              = 1.0;
21199326c5c6Sstefano_zampini   pcis->reusesubmatrices            = PETSC_TRUE;
21209326c5c6Sstefano_zampini   pcbddc->use_local_adj             = PETSC_TRUE;
21219326c5c6Sstefano_zampini   pcbddc->use_vertices              = PETSC_TRUE;
21229326c5c6Sstefano_zampini   pcbddc->use_edges                 = PETSC_TRUE;
21239326c5c6Sstefano_zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
21249326c5c6Sstefano_zampini   pcbddc->vertex_size               = 1;
21259326c5c6Sstefano_zampini   pcbddc->recompute_topography      = PETSC_TRUE;
21269326c5c6Sstefano_zampini   pcbddc->coarse_size               = -1;
21279326c5c6Sstefano_zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
21289326c5c6Sstefano_zampini   pcbddc->coarsening_ratio          = 8;
21299326c5c6Sstefano_zampini   pcbddc->coarse_eqs_per_proc       = 1;
21309326c5c6Sstefano_zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
21319326c5c6Sstefano_zampini   pcbddc->nedfield                  = -1;
21329326c5c6Sstefano_zampini   pcbddc->nedglobal                 = PETSC_TRUE;
21339326c5c6Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
21349326c5c6Sstefano_zampini   pcbddc->sub_schurs_layers         = -1;
21359326c5c6Sstefano_zampini   pcbddc->ksp_D                     = kspD;
21369326c5c6Sstefano_zampini   pcbddc->ksp_R                     = kspR;
21379326c5c6Sstefano_zampini   pcbddc->coarse_ksp                = kspC;
21389326c5c6Sstefano_zampini   PetscFunctionReturn(0);
21399326c5c6Sstefano_zampini }
21409326c5c6Sstefano_zampini 
21419326c5c6Sstefano_zampini PetscErrorCode PCDestroy_BDDC(PC pc)
21429326c5c6Sstefano_zampini {
21439326c5c6Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
21449326c5c6Sstefano_zampini   PetscErrorCode ierr;
21459326c5c6Sstefano_zampini 
21469326c5c6Sstefano_zampini   PetscFunctionBegin;
21479326c5c6Sstefano_zampini   ierr = PCReset_BDDC(pc);CHKERRQ(ierr);
21489326c5c6Sstefano_zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
21499326c5c6Sstefano_zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
21509326c5c6Sstefano_zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
2151a13144ffSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",NULL);CHKERRQ(ierr);
2152a198735bSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",NULL);CHKERRQ(ierr);
2153906d46d4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",NULL);CHKERRQ(ierr);
2154674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr);
215530368db7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",NULL);CHKERRQ(ierr);
2156bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr);
21572b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL);CHKERRQ(ierr);
2158b8ffe317SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL);CHKERRQ(ierr);
21592b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL);CHKERRQ(ierr);
2160bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
216182ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
2162bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
216382ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
2164bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
216582ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
2166bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
2167785d1243SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
2168bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr);
216963602bcaSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",NULL);CHKERRQ(ierr);
2170bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr);
2171bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr);
2172bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr);
2173bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr);
2174a06fd7f2SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",NULL);CHKERRQ(ierr);
2175ab8c8b98SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",NULL);CHKERRQ(ierr);
2176674ae819SStefano Zampini   ierr = PetscFree(pc->data);CHKERRQ(ierr);
2177da1bb401SStefano Zampini   PetscFunctionReturn(0);
2178da1bb401SStefano Zampini }
21791e6b0712SBarry Smith 
2180ab8c8b98SStefano Zampini static PetscErrorCode PCSetCoordinates_BDDC(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
2181ab8c8b98SStefano Zampini {
2182ab8c8b98SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2183ab8c8b98SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
2184ab8c8b98SStefano Zampini   PetscErrorCode ierr;
2185ab8c8b98SStefano Zampini 
2186ab8c8b98SStefano Zampini   PetscFunctionBegin;
2187ab8c8b98SStefano Zampini   ierr = PetscFree(mat_graph->coords);CHKERRQ(ierr);
2188ab8c8b98SStefano Zampini   ierr = PetscMalloc1(nloc*dim,&mat_graph->coords);CHKERRQ(ierr);
2189ab8c8b98SStefano Zampini   ierr = PetscMemcpy(mat_graph->coords,coords,nloc*dim*sizeof(PetscReal));CHKERRQ(ierr);
2190ab8c8b98SStefano Zampini   mat_graph->cnloc = nloc;
2191ab8c8b98SStefano Zampini   mat_graph->cdim  = dim;
2192ab8c8b98SStefano Zampini   mat_graph->cloc  = PETSC_FALSE;
2193ab8c8b98SStefano Zampini   PetscFunctionReturn(0);
2194ab8c8b98SStefano Zampini }
2195ab8c8b98SStefano Zampini 
2196a06fd7f2SStefano Zampini static PetscErrorCode PCPreSolveChangeRHS_BDDC(PC pc, PetscBool* change)
2197a06fd7f2SStefano Zampini {
2198a06fd7f2SStefano Zampini   PetscFunctionBegin;
2199a06fd7f2SStefano Zampini   *change = PETSC_TRUE;
2200a06fd7f2SStefano Zampini   PetscFunctionReturn(0);
2201a06fd7f2SStefano Zampini }
2202a06fd7f2SStefano Zampini 
22033425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
22043425bc38SStefano Zampini {
2205674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
2206266e20e9SStefano Zampini   Vec            work;
22073425bc38SStefano Zampini   PC_IS*         pcis;
22083425bc38SStefano Zampini   PC_BDDC*       pcbddc;
22093425bc38SStefano Zampini   PetscErrorCode ierr;
22100c7d97c5SJed Brown 
22113425bc38SStefano Zampini   PetscFunctionBegin;
22123425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
22133425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
22143425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
22153425bc38SStefano Zampini 
2216229984c5Sstefano_zampini   ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr);
2217229984c5Sstefano_zampini   /* copy rhs since we may change it during PCPreSolve_BDDC */
2218229984c5Sstefano_zampini   if (!pcbddc->original_rhs) {
2219229984c5Sstefano_zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
2220229984c5Sstefano_zampini   }
22216cc1294bSstefano_zampini   if (mat_ctx->rhs_flip) {
22226cc1294bSstefano_zampini     ierr = VecPointwiseMult(pcbddc->original_rhs,standard_rhs,mat_ctx->rhs_flip);CHKERRQ(ierr);
22236cc1294bSstefano_zampini   } else {
2224229984c5Sstefano_zampini     ierr = VecCopy(standard_rhs,pcbddc->original_rhs);CHKERRQ(ierr);
22256cc1294bSstefano_zampini   }
2226af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
2227229984c5Sstefano_zampini     /* interface pressure rhs */
2228022d8d2bSstefano_zampini     ierr = VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2229022d8d2bSstefano_zampini     ierr = VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2230229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2231229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
22326cc1294bSstefano_zampini     if (!mat_ctx->rhs_flip) {
2233229984c5Sstefano_zampini       ierr = VecScale(fetidp_flux_rhs,-1.);CHKERRQ(ierr);
2234229984c5Sstefano_zampini     }
22356cc1294bSstefano_zampini   }
2236c08af4c6SStefano Zampini   /*
2237c08af4c6SStefano Zampini      change of basis for physical rhs if needed
2238c08af4c6SStefano Zampini      It also changes the rhs in case of dirichlet boundaries
2239c08af4c6SStefano Zampini   */
22403738a8e6SStefano Zampini   ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,pcbddc->original_rhs,NULL);CHKERRQ(ierr);
2241fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
22423738a8e6SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcbddc->original_rhs,pcbddc->work_change);CHKERRQ(ierr);
22433738a8e6SStefano Zampini     work = pcbddc->work_change;
2244fc17d649SStefano Zampini    } else {
22453738a8e6SStefano Zampini     work = pcbddc->original_rhs;
2246fc17d649SStefano Zampini   }
22473425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
2248266e20e9SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2249266e20e9SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2250fb223d50SStefano Zampini   /* scale rhs since it should be unassembled */
2251fb223d50SStefano Zampini   /* TODO use counter scaling? (also below) */
2252266e20e9SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2253266e20e9SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2254674ae819SStefano Zampini   /* Apply partition of unity */
22553425bc38SStefano Zampini   ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
2256266e20e9SStefano Zampini   /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
22578eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
22583425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
22593425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
22603425bc38SStefano Zampini     ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr);
22613425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr);
2262266e20e9SStefano Zampini     ierr = VecSet(work,0.0);CHKERRQ(ierr);
2263266e20e9SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2264266e20e9SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2265266e20e9SStefano Zampini     /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
2266266e20e9SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2267266e20e9SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
22683425bc38SStefano Zampini     ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
22693425bc38SStefano Zampini   }
22703425bc38SStefano Zampini   /* BDDC rhs */
22713425bc38SStefano Zampini   ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr);
22728eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
22733425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
22743425bc38SStefano Zampini   }
22753425bc38SStefano Zampini   /* apply BDDC */
2276229984c5Sstefano_zampini   ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
2277dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
2278266e20e9SStefano Zampini   ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
2279229984c5Sstefano_zampini 
22803425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
22813425bc38SStefano Zampini   ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr);
22823425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
22833425bc38SStefano Zampini   ierr = VecScatterEnd(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2284229984c5Sstefano_zampini   /* Add contribution to interface pressures */
2285229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
2286229984c5Sstefano_zampini     ierr = MatMult(mat_ctx->B_BB,pcis->vec1_B,mat_ctx->vP);CHKERRQ(ierr);
2287229984c5Sstefano_zampini     if (pcbddc->switch_static) {
2288229984c5Sstefano_zampini       ierr = MatMultAdd(mat_ctx->B_BI,pcis->vec1_D,mat_ctx->vP,mat_ctx->vP);CHKERRQ(ierr);
2289229984c5Sstefano_zampini     }
2290229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2291229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2292229984c5Sstefano_zampini   }
22933425bc38SStefano Zampini   PetscFunctionReturn(0);
22943425bc38SStefano Zampini }
22951e6b0712SBarry Smith 
22963425bc38SStefano Zampini /*@
22970f202f7eSStefano Zampini  PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side
22983425bc38SStefano Zampini 
22993425bc38SStefano Zampini    Collective
23003425bc38SStefano Zampini 
23013425bc38SStefano Zampini    Input Parameters:
23020f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix object obtained by a call to PCBDDCCreateFETIDPOperators
23030f202f7eSStefano Zampini -  standard_rhs    - the right-hand side of the original linear system
23043425bc38SStefano Zampini 
23053425bc38SStefano Zampini    Output Parameters:
23060f202f7eSStefano Zampini .  fetidp_flux_rhs - the right-hand side for the FETI-DP linear system
23073425bc38SStefano Zampini 
23083425bc38SStefano Zampini    Level: developer
23093425bc38SStefano Zampini 
23103425bc38SStefano Zampini    Notes:
23113425bc38SStefano Zampini 
23120f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetSolution
23133425bc38SStefano Zampini @*/
23143425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
23153425bc38SStefano Zampini {
2316674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
23173425bc38SStefano Zampini   PetscErrorCode ierr;
23183425bc38SStefano Zampini 
23193425bc38SStefano Zampini   PetscFunctionBegin;
2320266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1);
2321266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_rhs,VEC_CLASSID,2);
2322266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_rhs,VEC_CLASSID,3);
23233425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
2324163d334eSBarry Smith   ierr = PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr);
23253425bc38SStefano Zampini   PetscFunctionReturn(0);
23263425bc38SStefano Zampini }
23271e6b0712SBarry Smith 
23283425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
23293425bc38SStefano Zampini {
2330674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
23313425bc38SStefano Zampini   PC_IS*         pcis;
23323425bc38SStefano Zampini   PC_BDDC*       pcbddc;
23333425bc38SStefano Zampini   PetscErrorCode ierr;
2334229984c5Sstefano_zampini   Vec            work;
23353425bc38SStefano Zampini 
23363425bc38SStefano Zampini   PetscFunctionBegin;
23373425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
23383425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
23393425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
23403425bc38SStefano Zampini 
23413425bc38SStefano Zampini   /* apply B_delta^T */
2342af140850Sstefano_zampini   ierr = VecSet(pcis->vec1_B,0.);CHKERRQ(ierr);
23433425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
23443425bc38SStefano Zampini   ierr = VecScatterEnd(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
23453425bc38SStefano Zampini   ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
2346229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
2347229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2348229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2349229984c5Sstefano_zampini     ierr = MatMultAdd(mat_ctx->Bt_BB,mat_ctx->vP,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
2350229984c5Sstefano_zampini   }
2351229984c5Sstefano_zampini 
23523425bc38SStefano Zampini   /* compute rhs for BDDC application */
23533425bc38SStefano Zampini   ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr);
23548eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
23553425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
2356229984c5Sstefano_zampini     if (mat_ctx->l2g_p) {
2357229984c5Sstefano_zampini       ierr = VecScale(mat_ctx->vP,-1.);CHKERRQ(ierr);
2358229984c5Sstefano_zampini       ierr = MatMultAdd(mat_ctx->Bt_BI,mat_ctx->vP,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr);
23593425bc38SStefano Zampini     }
2360229984c5Sstefano_zampini   }
2361229984c5Sstefano_zampini 
23623425bc38SStefano Zampini   /* apply BDDC */
2363229984c5Sstefano_zampini   ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
2364dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
2365229984c5Sstefano_zampini 
2366229984c5Sstefano_zampini   /* put values into global vector */
2367af140850Sstefano_zampini   if (pcbddc->ChangeOfBasisMatrix) work = pcbddc->work_change;
2368af140850Sstefano_zampini   else work = standard_sol;
2369229984c5Sstefano_zampini   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2370229984c5Sstefano_zampini   ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
23718eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
23723425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
23733425bc38SStefano Zampini     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr);
237400f6b531SStefano Zampini     ierr = VecAYPX(pcis->vec1_D,-1.0,mat_ctx->temp_solution_D);CHKERRQ(ierr);
237500f6b531SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr);
23763425bc38SStefano Zampini   }
2377229984c5Sstefano_zampini 
2378229984c5Sstefano_zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2379229984c5Sstefano_zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2380266e20e9SStefano Zampini   /* add p0 solution to final solution */
2381229984c5Sstefano_zampini   ierr = PCBDDCBenignGetOrSetP0(mat_ctx->pc,work,PETSC_FALSE);CHKERRQ(ierr);
2382fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2383af140850Sstefano_zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,work,standard_sol);CHKERRQ(ierr);
2384fc17d649SStefano Zampini   }
2385af140850Sstefano_zampini   ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr);
2386af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
2387229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2388229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2389229984c5Sstefano_zampini   }
23903425bc38SStefano Zampini   PetscFunctionReturn(0);
23913425bc38SStefano Zampini }
23921e6b0712SBarry Smith 
23933425bc38SStefano Zampini /*@
23940f202f7eSStefano Zampini  PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system
23953425bc38SStefano Zampini 
23963425bc38SStefano Zampini    Collective
23973425bc38SStefano Zampini 
23983425bc38SStefano Zampini    Input Parameters:
23990f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators
24000f202f7eSStefano Zampini -  fetidp_flux_sol - the solution of the FETI-DP linear system
24013425bc38SStefano Zampini 
24023425bc38SStefano Zampini    Output Parameters:
24030f202f7eSStefano Zampini .  standard_sol    - the solution defined on the physical domain
24043425bc38SStefano Zampini 
24053425bc38SStefano Zampini    Level: developer
24063425bc38SStefano Zampini 
24073425bc38SStefano Zampini    Notes:
24083425bc38SStefano Zampini 
24090f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetRHS
24103425bc38SStefano Zampini @*/
24113425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
24123425bc38SStefano Zampini {
2413674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
24143425bc38SStefano Zampini   PetscErrorCode ierr;
24153425bc38SStefano Zampini 
24163425bc38SStefano Zampini   PetscFunctionBegin;
2417266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1);
2418266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_sol,VEC_CLASSID,2);
2419266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_sol,VEC_CLASSID,3);
24203425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
2421163d334eSBarry Smith   ierr = PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr);
24223425bc38SStefano Zampini   PetscFunctionReturn(0);
24233425bc38SStefano Zampini }
24241e6b0712SBarry Smith 
2425547c9a8eSstefano_zampini static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, PetscBool fully_redundant, const char* prefix, Mat *fetidp_mat, PC *fetidp_pc)
24263425bc38SStefano Zampini {
2427674ae819SStefano Zampini 
2428674ae819SStefano Zampini   FETIDPMat_ctx  fetidpmat_ctx;
24293425bc38SStefano Zampini   Mat            newmat;
2430674ae819SStefano Zampini   FETIDPPC_ctx   fetidppc_ctx;
24313425bc38SStefano Zampini   PC             newpc;
2432ce94432eSBarry Smith   MPI_Comm       comm;
24333425bc38SStefano Zampini   PetscErrorCode ierr;
24343425bc38SStefano Zampini 
24353425bc38SStefano Zampini   PetscFunctionBegin;
2436ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
24373425bc38SStefano Zampini   /* FETIDP linear matrix */
24383425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr);
24391720468bSStefano Zampini   fetidpmat_ctx->fully_redundant = fully_redundant;
24403425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr);
2441a5bb87b3Sstefano_zampini   ierr = MatCreateShell(comm,fetidpmat_ctx->n,fetidpmat_ctx->n,fetidpmat_ctx->N,fetidpmat_ctx->N,fetidpmat_ctx,&newmat);CHKERRQ(ierr);
24423425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr);
2443edf7251bSStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT_TRANSPOSE,(void (*)(void))FETIDPMatMultTranspose);CHKERRQ(ierr);
24443425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr);
2445547c9a8eSstefano_zampini   ierr = MatSetOptionsPrefix(newmat,prefix);CHKERRQ(ierr);
2446547c9a8eSstefano_zampini   ierr = MatAppendOptionsPrefix(newmat,"fetidp_");CHKERRQ(ierr);
24473425bc38SStefano Zampini   ierr = MatSetUp(newmat);CHKERRQ(ierr);
24483425bc38SStefano Zampini   /* FETIDP preconditioner */
24493425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr);
24503425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr);
24513425bc38SStefano Zampini   ierr = PCCreate(comm,&newpc);CHKERRQ(ierr);
2452e1214c54Sstefano_zampini   ierr = PCSetOperators(newpc,newmat,newmat);CHKERRQ(ierr);
2453e1214c54Sstefano_zampini   ierr = PCSetOptionsPrefix(newpc,prefix);CHKERRQ(ierr);
2454e1214c54Sstefano_zampini   ierr = PCAppendOptionsPrefix(newpc,"fetidp_");CHKERRQ(ierr);
2455*399ffe99SStefano Zampini   ierr = PCSetErrorIfFailure(newpc,pc->erroriffailure);CHKERRQ(ierr);
2456e1214c54Sstefano_zampini   if (!fetidpmat_ctx->l2g_lambda_only) {
24573425bc38SStefano Zampini     ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
24583425bc38SStefano Zampini     ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr);
24593425bc38SStefano Zampini     ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr);
2460edf7251bSStefano Zampini     ierr = PCShellSetApplyTranspose(newpc,FETIDPPCApplyTranspose);CHKERRQ(ierr);
2461c45b8d2dSstefano_zampini     ierr = PCShellSetView(newpc,FETIDPPCView);CHKERRQ(ierr);
24623425bc38SStefano Zampini     ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
2463e1214c54Sstefano_zampini   } else {
2464e1214c54Sstefano_zampini     KSP      *ksps;
2465e1214c54Sstefano_zampini     PC       lagpc;
2466e1214c54Sstefano_zampini     Mat      M,AM,PM;
2467e1214c54Sstefano_zampini     PetscInt nn;
2468e1214c54Sstefano_zampini 
2469e1214c54Sstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_PPmat",(PetscObject*)&M);CHKERRQ(ierr);
2470e1214c54Sstefano_zampini     ierr = PCSetType(newpc,PCFIELDSPLIT);CHKERRQ(ierr);
2471e1214c54Sstefano_zampini     ierr = PCFieldSplitSetIS(newpc,"lag",fetidpmat_ctx->lagrange);CHKERRQ(ierr);
2472e1214c54Sstefano_zampini     ierr = PCFieldSplitSetIS(newpc,"p",fetidpmat_ctx->pressure);CHKERRQ(ierr);
2473e1214c54Sstefano_zampini     ierr = PCFieldSplitSetType(newpc,PC_COMPOSITE_SCHUR);CHKERRQ(ierr);
247440c75d76SStefano Zampini     ierr = PCFieldSplitSetSchurFactType(newpc,PC_FIELDSPLIT_SCHUR_FACT_DIAG);CHKERRQ(ierr);
2475e1214c54Sstefano_zampini     ierr = PCFieldSplitSetSchurPre(newpc,PC_FIELDSPLIT_SCHUR_PRE_USER,M);CHKERRQ(ierr);
2476c096484dSStefano Zampini     ierr = PCFieldSplitSetSchurScale(newpc,1.0);CHKERRQ(ierr);
2477e1214c54Sstefano_zampini     ierr = PCSetFromOptions(newpc);CHKERRQ(ierr);
2478e1214c54Sstefano_zampini     ierr = PCSetUp(newpc);CHKERRQ(ierr);
2479e1214c54Sstefano_zampini 
2480e1214c54Sstefano_zampini     /* set the solver for the (0,0) block */
248140c75d76SStefano Zampini     ierr = PCFieldSplitGetSubKSP(newpc,&nn,&ksps);CHKERRQ(ierr);
2482e1214c54Sstefano_zampini     ierr = PCCreate(comm,&lagpc);CHKERRQ(ierr);
2483e1214c54Sstefano_zampini     ierr = PCSetType(lagpc,PCSHELL);CHKERRQ(ierr);
2484e1214c54Sstefano_zampini     ierr = KSPGetOperators(ksps[0],&AM,&PM);CHKERRQ(ierr);
2485e1214c54Sstefano_zampini     ierr = PCSetOperators(lagpc,AM,PM);CHKERRQ(ierr);
2486e1214c54Sstefano_zampini     ierr = PCShellSetContext(lagpc,fetidppc_ctx);CHKERRQ(ierr);
2487e1214c54Sstefano_zampini     ierr = PCShellSetApply(lagpc,FETIDPPCApply);CHKERRQ(ierr);
2488e1214c54Sstefano_zampini     ierr = PCShellSetApplyTranspose(lagpc,FETIDPPCApplyTranspose);CHKERRQ(ierr);
2489e1214c54Sstefano_zampini     ierr = PCShellSetView(lagpc,FETIDPPCView);CHKERRQ(ierr);
2490e1214c54Sstefano_zampini     ierr = PCShellSetDestroy(lagpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
2491e1214c54Sstefano_zampini     ierr = KSPSetPC(ksps[0],lagpc);CHKERRQ(ierr);
2492e1214c54Sstefano_zampini     ierr = PCDestroy(&lagpc);CHKERRQ(ierr);
2493e1214c54Sstefano_zampini     ierr = PetscFree(ksps);CHKERRQ(ierr);
2494e1214c54Sstefano_zampini   }
24953425bc38SStefano Zampini   /* return pointers for objects created */
24963425bc38SStefano Zampini   *fetidp_mat = newmat;
24973425bc38SStefano Zampini   *fetidp_pc = newpc;
24983425bc38SStefano Zampini   PetscFunctionReturn(0);
24993425bc38SStefano Zampini }
25001e6b0712SBarry Smith 
250194ef8ddeSSatish Balay /*@C
25020f202f7eSStefano Zampini  PCBDDCCreateFETIDPOperators - Create FETI-DP operators
25033425bc38SStefano Zampini 
25043425bc38SStefano Zampini    Collective
25053425bc38SStefano Zampini 
25063425bc38SStefano Zampini    Input Parameters:
25071720468bSStefano Zampini +  pc - the BDDC preconditioning context (setup should have been called before)
2508547c9a8eSstefano_zampini .  fully_redundant - true for a fully redundant set of Lagrange multipliers
2509547c9a8eSstefano_zampini -  prefix - optional options database prefix for the objects to be created (can be NULL)
251028509bceSStefano Zampini 
251128509bceSStefano Zampini    Output Parameters:
25120f202f7eSStefano Zampini +  fetidp_mat - shell FETI-DP matrix object
25130f202f7eSStefano Zampini -  fetidp_pc  - shell Dirichlet preconditioner for FETI-DP matrix
251428509bceSStefano Zampini 
25153425bc38SStefano Zampini    Level: developer
25163425bc38SStefano Zampini 
25173425bc38SStefano Zampini    Notes:
25180f202f7eSStefano Zampini      Currently the only operations provided for FETI-DP matrix are MatMult and MatMultTranspose
25193425bc38SStefano Zampini 
25200f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCMatFETIDPGetRHS, PCBDDCMatFETIDPGetSolution
25213425bc38SStefano Zampini @*/
2522547c9a8eSstefano_zampini PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc)
25233425bc38SStefano Zampini {
25243425bc38SStefano Zampini   PetscErrorCode ierr;
25253425bc38SStefano Zampini 
25263425bc38SStefano Zampini   PetscFunctionBegin;
25273425bc38SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
25283425bc38SStefano Zampini   if (pc->setupcalled) {
2529547c9a8eSstefano_zampini     ierr = PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,PetscBool,const char*,Mat*,PC*),(pc,fully_redundant,prefix,fetidp_mat,fetidp_pc));CHKERRQ(ierr);
25304247aa23Sstefano_zampini   } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"You must call PCSetup_BDDC() first \n");
25313425bc38SStefano Zampini   PetscFunctionReturn(0);
25323425bc38SStefano Zampini }
25330c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
2534da1bb401SStefano Zampini /*MC
2535da1bb401SStefano Zampini    PCBDDC - Balancing Domain Decomposition by Constraints.
25360c7d97c5SJed Brown 
253728509bceSStefano Zampini    An implementation of the BDDC preconditioner based on
253828509bceSStefano Zampini 
253928509bceSStefano Zampini .vb
254028509bceSStefano Zampini    [1] C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
254128509bceSStefano 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
254228509bceSStefano Zampini    [3] J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", http://arxiv.org/abs/0712.3977
25430f202f7eSStefano 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
254428509bceSStefano Zampini .ve
254528509bceSStefano Zampini 
254628509bceSStefano Zampini    The matrix to be preconditioned (Pmat) must be of type MATIS.
254728509bceSStefano Zampini 
25480f202f7eSStefano Zampini    Currently works with MATIS matrices with local matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers.
254928509bceSStefano Zampini 
255028509bceSStefano Zampini    It also works with unsymmetric and indefinite problems.
255128509bceSStefano Zampini 
2552b6fdb6dfSStefano 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.
2553b6fdb6dfSStefano Zampini 
2554c7017625SStefano 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).
255528509bceSStefano Zampini 
25560f202f7eSStefano 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()
255730368db7SStefano Zampini    Additional information on dofs can be provided by using PCBDDCSetDofsSplitting(), PCBDDCSetDirichletBoundaries(), PCBDDCSetNeumannBoundaries(), and PCBDDCSetPrimalVerticesIS() and their local counterparts.
255828509bceSStefano Zampini 
25590f202f7eSStefano Zampini    Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). Non-singular modes are retained via SVD.
256028509bceSStefano Zampini 
25610f202f7eSStefano 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.
25620f202f7eSStefano Zampini    User defined change of basis can be passed to PCBDDC by using PCBDDCSetChangeOfBasisMat()
256328509bceSStefano Zampini 
25640f202f7eSStefano Zampini    The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using a MatPartitioning object.
256528509bceSStefano Zampini 
2566df4d28bfSStefano 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.
256728509bceSStefano Zampini 
25680f202f7eSStefano 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.
25690f202f7eSStefano Zampini    Deluxe scaling is not supported yet for FETI-DP.
25700f202f7eSStefano Zampini 
25710f202f7eSStefano Zampini    Options Database Keys (some of them, run with -h for a complete list):
25720f202f7eSStefano Zampini 
25730f202f7eSStefano Zampini .    -pc_bddc_use_vertices <true> - use or not vertices in primal space
25740f202f7eSStefano Zampini .    -pc_bddc_use_edges <true> - use or not edges in primal space
25750f202f7eSStefano Zampini .    -pc_bddc_use_faces <false> - use or not faces in primal space
25760f202f7eSStefano Zampini .    -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems
25770f202f7eSStefano Zampini .    -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only)
25780f202f7eSStefano Zampini .    -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested
25790f202f7eSStefano Zampini .    -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1])
258028509bceSStefano Zampini .    -pc_bddc_levels <0> - maximum number of levels for multilevel
25810f202f7eSStefano 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)
25825459c157SBarry 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)
25830f202f7eSStefano Zampini .    -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling
25840f202f7eSStefano 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)
2585bd2a564bSStefano 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)
258628509bceSStefano Zampini -    -pc_bddc_check_level <0> - set verbosity level of debugging output
258728509bceSStefano Zampini 
258828509bceSStefano Zampini    Options for Dirichlet, Neumann or coarse solver can be set with
258928509bceSStefano Zampini .vb
259028509bceSStefano Zampini       -pc_bddc_dirichlet_
259128509bceSStefano Zampini       -pc_bddc_neumann_
259228509bceSStefano Zampini       -pc_bddc_coarse_
259328509bceSStefano Zampini .ve
25940f202f7eSStefano Zampini    e.g -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. PCBDDC uses by default KPSPREONLY and PCLU.
259528509bceSStefano Zampini 
25960f202f7eSStefano Zampini    When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified as
259728509bceSStefano Zampini .vb
2598312be037SStefano Zampini       -pc_bddc_dirichlet_lN_
2599312be037SStefano Zampini       -pc_bddc_neumann_lN_
2600312be037SStefano Zampini       -pc_bddc_coarse_lN_
260128509bceSStefano Zampini .ve
26020f202f7eSStefano Zampini    Note that level number ranges from the finest (0) to the coarsest (N).
26030f202f7eSStefano 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.
26040f202f7eSStefano Zampini .vb
26050f202f7eSStefano Zampini      -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3
26060f202f7eSStefano Zampini .ve
26070f202f7eSStefano 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
2608da1bb401SStefano Zampini 
2609da1bb401SStefano Zampini    Level: intermediate
2610da1bb401SStefano Zampini 
2611e94cfbe0SPatrick Sanan    Developer Notes:
2612da1bb401SStefano Zampini 
2613da1bb401SStefano Zampini    Contributed by Stefano Zampini
2614da1bb401SStefano Zampini 
2615da1bb401SStefano Zampini .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
2616da1bb401SStefano Zampini M*/
2617b2573a8aSBarry Smith 
26188cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
2619da1bb401SStefano Zampini {
2620da1bb401SStefano Zampini   PetscErrorCode      ierr;
2621da1bb401SStefano Zampini   PC_BDDC             *pcbddc;
2622da1bb401SStefano Zampini 
2623da1bb401SStefano Zampini   PetscFunctionBegin;
2624b00a9115SJed Brown   ierr     = PetscNewLog(pc,&pcbddc);CHKERRQ(ierr);
2625da1bb401SStefano Zampini   pc->data = (void*)pcbddc;
2626da1bb401SStefano Zampini 
2627da1bb401SStefano Zampini   /* create PCIS data structure */
2628da1bb401SStefano Zampini   ierr = PCISCreate(pc);CHKERRQ(ierr);
2629da1bb401SStefano Zampini 
26309326c5c6Sstefano_zampini   /* create local graph structure */
26319326c5c6Sstefano_zampini   ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr);
26329326c5c6Sstefano_zampini 
26339326c5c6Sstefano_zampini   /* BDDC nonzero defaults */
263408a5cf49SStefano Zampini   pcbddc->use_local_adj             = PETSC_TRUE;
263547d04d0dSStefano Zampini   pcbddc->use_vertices              = PETSC_TRUE;
263647d04d0dSStefano Zampini   pcbddc->use_edges                 = PETSC_TRUE;
26373301b35fSStefano Zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
263814f95afaSStefano Zampini   pcbddc->vertex_size               = 1;
2639c703fcc7SStefano Zampini   pcbddc->recompute_topography      = PETSC_TRUE;
264068457ee5SStefano Zampini   pcbddc->coarse_size               = -1;
264185c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
264247d04d0dSStefano Zampini   pcbddc->coarsening_ratio          = 8;
264357de7509SStefano Zampini   pcbddc->coarse_eqs_per_proc       = 1;
264427b6a85dSStefano Zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
26451e0482f5SStefano Zampini   pcbddc->nedfield                  = -1;
26461e0482f5SStefano Zampini   pcbddc->nedglobal                 = PETSC_TRUE;
2647be12c134Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
2648b96c3477SStefano Zampini   pcbddc->sub_schurs_layers         = -1;
2649bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[0]     = 0.0;
2650bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[1]     = 0.0;
2651b7eb3628SStefano Zampini 
2652da1bb401SStefano Zampini   /* function pointers */
2653da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
265493bd9ae7SStefano Zampini   pc->ops->applytranspose      = PCApplyTranspose_BDDC;
2655da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
2656da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
2657da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
26586b78500eSPatrick Sanan   pc->ops->view                = PCView_BDDC;
2659da1bb401SStefano Zampini   pc->ops->applyrichardson     = 0;
2660da1bb401SStefano Zampini   pc->ops->applysymmetricleft  = 0;
2661da1bb401SStefano Zampini   pc->ops->applysymmetricright = 0;
2662534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
2663534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
26649326c5c6Sstefano_zampini   pc->ops->reset               = PCReset_BDDC;
2665da1bb401SStefano Zampini 
2666da1bb401SStefano Zampini   /* composing function */
2667a13144ffSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",PCBDDCSetDiscreteGradient_BDDC);CHKERRQ(ierr);
2668a198735bSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",PCBDDCSetDivergenceMat_BDDC);CHKERRQ(ierr);
2669906d46d4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",PCBDDCSetChangeOfBasisMat_BDDC);CHKERRQ(ierr);
2670674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
267130368db7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",PCBDDCSetPrimalVerticesIS_BDDC);CHKERRQ(ierr);
2672bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr);
26732b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC);CHKERRQ(ierr);
2674b8ffe317SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC);CHKERRQ(ierr);
26752b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC);CHKERRQ(ierr);
2676bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
267782ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",PCBDDCSetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
2678bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
267982ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",PCBDDCSetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
2680bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
268182ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",PCBDDCGetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
2682bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
268382ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",PCBDDCGetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
2684bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
268563602bcaSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",PCBDDCSetDofsSplittingLocal_BDDC);CHKERRQ(ierr);
2686bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
2687bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr);
2688bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr);
2689bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr);
2690a06fd7f2SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",PCPreSolveChangeRHS_BDDC);CHKERRQ(ierr);
2691ab8c8b98SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",PCSetCoordinates_BDDC);CHKERRQ(ierr);
2692da1bb401SStefano Zampini   PetscFunctionReturn(0);
2693da1bb401SStefano Zampini }
269443371fb9SStefano Zampini 
269543371fb9SStefano Zampini /*@C
269643371fb9SStefano Zampini  PCBDDCInitializePackage - This function initializes everything in the PCBDDC package. It is called
269743371fb9SStefano Zampini     from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to PCCreate_BDDC()
269843371fb9SStefano Zampini     when using static libraries.
269943371fb9SStefano Zampini 
270043371fb9SStefano Zampini  Level: developer
270143371fb9SStefano Zampini 
270243371fb9SStefano Zampini  .keywords: PC, PCBDDC, initialize, package
270343371fb9SStefano Zampini  .seealso: PetscInitialize()
270443371fb9SStefano Zampini @*/
270543371fb9SStefano Zampini PetscErrorCode PCBDDCInitializePackage(void)
270643371fb9SStefano Zampini {
270743371fb9SStefano Zampini   PetscErrorCode ierr;
270843371fb9SStefano Zampini   int            i;
270943371fb9SStefano Zampini 
271043371fb9SStefano Zampini   PetscFunctionBegin;
271143371fb9SStefano Zampini   if (PCBDDCPackageInitialized) PetscFunctionReturn(0);
271243371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_TRUE;
271343371fb9SStefano Zampini   ierr = PetscRegisterFinalize(PCBDDCFinalizePackage);CHKERRQ(ierr);
271443371fb9SStefano Zampini 
271543371fb9SStefano Zampini   /* general events */
271643371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCTopo",PC_CLASSID,&PC_BDDC_Topology[0]);CHKERRQ(ierr);
271743371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCLKSP",PC_CLASSID,&PC_BDDC_LocalSolvers[0]);CHKERRQ(ierr);
271843371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCLWor",PC_CLASSID,&PC_BDDC_LocalWork[0]);CHKERRQ(ierr);
271943371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCCorr",PC_CLASSID,&PC_BDDC_CorrectionSetUp[0]);CHKERRQ(ierr);
272043371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCCSet",PC_CLASSID,&PC_BDDC_CoarseSetUp[0]);CHKERRQ(ierr);
272143371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCCKSP",PC_CLASSID,&PC_BDDC_CoarseSolver[0]);CHKERRQ(ierr);
272243371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCAdap",PC_CLASSID,&PC_BDDC_AdaptiveSetUp[0]);CHKERRQ(ierr);
272343371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCScal",PC_CLASSID,&PC_BDDC_Scaling[0]);CHKERRQ(ierr);
272443371fb9SStefano Zampini   ierr = PetscLogEventRegister("PCBDDCSchr",PC_CLASSID,&PC_BDDC_Schurs[0]);CHKERRQ(ierr);
272543371fb9SStefano Zampini   for (i=1;i<PETSC_PCBDDC_MAXLEVELS;i++) {
272643371fb9SStefano Zampini     char ename[32];
272743371fb9SStefano Zampini 
272843371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCTopo l%02d",i);CHKERRQ(ierr);
272943371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Topology[i]);CHKERRQ(ierr);
273043371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCLKSP l%02d",i);CHKERRQ(ierr);
273143371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_LocalSolvers[i]);CHKERRQ(ierr);
273243371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCLWor l%02d",i);CHKERRQ(ierr);
273343371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_LocalWork[i]);CHKERRQ(ierr);
273443371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCCorr l%02d",i);CHKERRQ(ierr);
273543371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CorrectionSetUp[i]);CHKERRQ(ierr);
273643371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCCSet l%02d",i);CHKERRQ(ierr);
273743371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CoarseSetUp[i]);CHKERRQ(ierr);
273843371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCCKSP l%02d",i);CHKERRQ(ierr);
273943371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_CoarseSolver[i]);CHKERRQ(ierr);
274043371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCAdap l%02d",i);CHKERRQ(ierr);
274143371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_AdaptiveSetUp[i]);CHKERRQ(ierr);
274243371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCScal l%02d",i);CHKERRQ(ierr);
274343371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Scaling[i]);CHKERRQ(ierr);
274443371fb9SStefano Zampini     ierr = PetscSNPrintf(ename,sizeof(ename),"PCBDDCSchr l%02d",i);CHKERRQ(ierr);
274543371fb9SStefano Zampini     ierr = PetscLogEventRegister(ename,PC_CLASSID,&PC_BDDC_Schurs[i]);CHKERRQ(ierr);
274643371fb9SStefano Zampini   }
274743371fb9SStefano Zampini   PetscFunctionReturn(0);
274843371fb9SStefano Zampini }
274943371fb9SStefano Zampini 
275043371fb9SStefano Zampini /*@C
275143371fb9SStefano Zampini  PCBDDCFinalizePackage - This function frees everything from the PCBDDC package. It is
275243371fb9SStefano Zampini     called from PetscFinalize() automatically.
275343371fb9SStefano Zampini 
275443371fb9SStefano Zampini  Level: developer
275543371fb9SStefano Zampini 
275643371fb9SStefano Zampini  .keywords: Petsc, destroy, package
275743371fb9SStefano Zampini  .seealso: PetscFinalize()
275843371fb9SStefano Zampini @*/
275943371fb9SStefano Zampini PetscErrorCode PCBDDCFinalizePackage(void)
276043371fb9SStefano Zampini {
276143371fb9SStefano Zampini   PetscFunctionBegin;
276243371fb9SStefano Zampini   PCBDDCPackageInitialized = PETSC_FALSE;
276343371fb9SStefano Zampini   PetscFunctionReturn(0);
276443371fb9SStefano Zampini }
2765