xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 37ebbdf77aa7dc0b8b390527ee6283c66bc2d004)
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 
26f3d41395Sstefano_zampini static PetscBool  cited = PETSC_FALSE;
27f3d41395Sstefano_zampini static const char citation[] =
28f3d41395Sstefano_zampini "@article{ZampiniPCBDDC,\n"
29f3d41395Sstefano_zampini "author = {Stefano Zampini},\n"
30f3d41395Sstefano_zampini "title = {{PCBDDC}: A Class of Robust Dual-Primal Methods in {PETS}c},\n"
31f3d41395Sstefano_zampini "journal = {SIAM Journal on Scientific Computing},\n"
32f3d41395Sstefano_zampini "volume = {38},\n"
33f3d41395Sstefano_zampini "number = {5},\n"
34f3d41395Sstefano_zampini "pages = {S282-S306},\n"
35f3d41395Sstefano_zampini "year = {2016},\n"
36f3d41395Sstefano_zampini "doi = {10.1137/15M1025785},\n"
37f3d41395Sstefano_zampini "URL = {http://dx.doi.org/10.1137/15M1025785},\n"
38f3d41395Sstefano_zampini "eprint = {http://dx.doi.org/10.1137/15M1025785}\n"
39f3d41395Sstefano_zampini "}\n";
40f3d41395Sstefano_zampini 
410369aaf7SStefano Zampini /* temporarily declare it */
420369aaf7SStefano Zampini PetscErrorCode PCApply_BDDC(PC,Vec,Vec);
430369aaf7SStefano Zampini 
444416b707SBarry Smith PetscErrorCode PCSetFromOptions_BDDC(PetscOptionItems *PetscOptionsObject,PC pc)
450c7d97c5SJed Brown {
460c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
47bd2a564bSStefano Zampini   PetscInt       nt;
480c7d97c5SJed Brown   PetscErrorCode ierr;
490c7d97c5SJed Brown 
500c7d97c5SJed Brown   PetscFunctionBegin;
51e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"BDDC options");CHKERRQ(ierr);
528eeda7d8SStefano Zampini   /* Verbose debugging */
53a13144ffSStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_check_level","Verbose output for PCBDDC (intended for debug)","none",pcbddc->dbg_flag,&pcbddc->dbg_flag,NULL);CHKERRQ(ierr);
54a13144ffSStefano Zampini   /* Approximate solvers */
55c7017625SStefano 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);
56c7017625SStefano 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);
57c7017625SStefano 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);
58c7017625SStefano 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);
596b78500eSPatrick Sanan   /* Primal space customization */
6008a5cf49SStefano 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);
61be12c134Sstefano_zampini   ierr = PetscOptionsInt("-pc_bddc_graph_maxcount","Maximum number of shared subdomains for a connected component","none",pcbddc->graphmaxcount,&pcbddc->graphmaxcount,NULL);CHKERRQ(ierr);
621c7a958bSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_corner_selection","Activates face-based corner selection","none",pcbddc->corner_selection,&pcbddc->corner_selection,NULL);CHKERRQ(ierr);
638eeda7d8SStefano 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);
648eeda7d8SStefano 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);
658eeda7d8SStefano 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);
6614f95afaSStefano 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);
676661aa1dSStefano 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);
6814f95afaSStefano 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);
698eeda7d8SStefano Zampini   /* Change of basis */
70b9b85e73SStefano 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);
71b9b85e73SStefano 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);
72674ae819SStefano Zampini   if (!pcbddc->use_change_of_basis) {
73674ae819SStefano Zampini     pcbddc->use_change_on_faces = PETSC_FALSE;
74674ae819SStefano Zampini   }
758eeda7d8SStefano Zampini   /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */
768eeda7d8SStefano 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);
7757de7509SStefano 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);
780298fd71SBarry Smith   ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","none",pcbddc->coarsening_ratio,&pcbddc->coarsening_ratio,NULL);CHKERRQ(ierr);
792b510759SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_levels","Set maximum number of levels for multilevel","none",pcbddc->max_levels,&pcbddc->max_levels,NULL);CHKERRQ(ierr);
80323d395dSStefano 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);
81674ae819SStefano 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);
82b96c3477SStefano 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);
83b96c3477SStefano 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);
84b96c3477SStefano 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);
85683d3df6SStefano 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);
86bf3a8328SStefano 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);
87839e9adbSstefano_zampini   ierr = PetscOptionsBool("-pc_bddc_deluxe_singlemat","Collapse deluxe operators","none",pcbddc->deluxe_singlemat,&pcbddc->deluxe_singlemat,NULL);CHKERRQ(ierr);
88bf3a8328SStefano 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);
89bd2a564bSStefano Zampini   nt   = 2;
90bd2a564bSStefano Zampini   ierr = PetscOptionsRealArray("-pc_bddc_adaptive_threshold","Thresholds to be used for adaptive selection of constraints","none",pcbddc->adaptive_threshold,&nt,NULL);CHKERRQ(ierr);
91bd2a564bSStefano Zampini   if (nt == 1) pcbddc->adaptive_threshold[1] = pcbddc->adaptive_threshold[0];
9208122e43SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_adaptive_nmin","Minimum number of constraints per connected components","none",pcbddc->adaptive_nmin,&pcbddc->adaptive_nmin,NULL);CHKERRQ(ierr);
9308122e43SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_adaptive_nmax","Maximum number of constraints per connected components","none",pcbddc->adaptive_nmax,&pcbddc->adaptive_nmax,NULL);CHKERRQ(ierr);
943301b35fSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_symmetric","Symmetric computation of primal basis functions","none",pcbddc->symmetric_primal,&pcbddc->symmetric_primal,NULL);CHKERRQ(ierr);
95b0c7d250SStefano 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);
96b3afcdbeSStefano 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);
97e9627c49SStefano 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);
9827b6a85dSStefano 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);
99a198735bSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_nonetflux","Automatic computation of no-net-flux quadrature weights","none",pcbddc->compute_nonetflux,&pcbddc->compute_nonetflux,NULL);CHKERRQ(ierr);
1004f1b2e48SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_detect_disconnected","Detects disconnected subdomains","none",pcbddc->detect_disconnected,&pcbddc->detect_disconnected,NULL);CHKERRQ(ierr);
1018361f951SStefano 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);
10270c64980SStefano 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);
1030c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
1040c7d97c5SJed Brown   PetscFunctionReturn(0);
1050c7d97c5SJed Brown }
1066b78500eSPatrick Sanan 
1076b78500eSPatrick Sanan static PetscErrorCode PCView_BDDC(PC pc,PetscViewer viewer)
1086b78500eSPatrick Sanan {
1096b78500eSPatrick Sanan   PC_BDDC              *pcbddc = (PC_BDDC*)pc->data;
110e9627c49SStefano Zampini   PC_IS                *pcis = (PC_IS*)pc->data;
1116b78500eSPatrick Sanan   PetscErrorCode       ierr;
11271783a16SStefano Zampini   PetscBool            isascii;
113e9627c49SStefano Zampini   PetscSubcomm         subcomm;
114e9627c49SStefano Zampini   PetscViewer          subviewer;
1156b78500eSPatrick Sanan 
1166b78500eSPatrick Sanan   PetscFunctionBegin;
1176b78500eSPatrick Sanan   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1186b78500eSPatrick Sanan   /* ASCII viewer */
1196b78500eSPatrick Sanan   if (isascii) {
1204b2aedd3SStefano Zampini     PetscMPIInt   color,rank,size;
121fbad9177SStefano Zampini     PetscInt64    loc[7],gsum[6],gmax[6],gmin[6],totbenign;
122e9627c49SStefano Zampini     PetscScalar   interface_size;
123e9627c49SStefano Zampini     PetscReal     ratio1=0.,ratio2=0.;
124e9627c49SStefano Zampini     Vec           counter;
1256b78500eSPatrick Sanan 
126b74ba07aSstefano_zampini     if (!pc->setupcalled) {
127b74ba07aSstefano_zampini       ierr = PetscViewerASCIIPrintf(viewer,"  Partial information available: preconditioner has not been setup yet\n");CHKERRQ(ierr);
128b74ba07aSstefano_zampini     }
129efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use verbose output: %D\n",pcbddc->dbg_flag);CHKERRQ(ierr);
1306f0c0a6aSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Use user-defined CSR: %d\n",!!pcbddc->mat_graph->nvtxs_csr);CHKERRQ(ierr);
1316f0c0a6aSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Use local mat graph: %d\n",pcbddc->use_local_adj && !pcbddc->mat_graph->nvtxs_csr);CHKERRQ(ierr);
132e9627c49SStefano Zampini     if (pcbddc->mat_graph->twodim) {
133efd4aadfSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Connectivity graph topological dimension: 2\n");CHKERRQ(ierr);
134e9627c49SStefano Zampini     } else {
135efd4aadfSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Connectivity graph topological dimension: 3\n");CHKERRQ(ierr);
136e9627c49SStefano Zampini     }
137aefa1729SStefano Zampini     if (pcbddc->graphmaxcount != PETSC_MAX_INT) {
138efd4aadfSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"  Graph max count: %D\n",pcbddc->graphmaxcount);CHKERRQ(ierr);
139aefa1729SStefano Zampini     }
14050e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Use vertices: %d (vertex size %D)\n",pcbddc->use_vertices,pcbddc->vertex_size);CHKERRQ(ierr);
141efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use edges: %d\n",pcbddc->use_edges);CHKERRQ(ierr);
142efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use faces: %d\n",pcbddc->use_faces);CHKERRQ(ierr);
143efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use true near null space: %d\n",pcbddc->use_nnsp_true);CHKERRQ(ierr);
144efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use QR for single constraints on cc: %d\n",pcbddc->use_qr_single);CHKERRQ(ierr);
145efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use change of basis on local edge nodes: %d\n",pcbddc->use_change_of_basis);CHKERRQ(ierr);
146efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use change of basis on local face nodes: %d\n",pcbddc->use_change_on_faces);CHKERRQ(ierr);
147efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  User defined change of basis matrix: %d\n",!!pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
148efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Has change of basis matrix: %d\n",!!pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
149efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Eliminate dirichlet boundary dofs: %d\n",pcbddc->eliminate_dirdofs);CHKERRQ(ierr);
150efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Switch on static condensation ops around the interface preconditioner: %d\n",pcbddc->switch_static);CHKERRQ(ierr);
151efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use exact dirichlet trick: %d\n",pcbddc->use_exact_dirichlet_trick);CHKERRQ(ierr);
15250e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Multilevel max levels: %D\n",pcbddc->max_levels);CHKERRQ(ierr);
15350e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Multilevel coarsening ratio: %D\n",pcbddc->coarsening_ratio);CHKERRQ(ierr);
154efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use estimated eigs for coarse problem: %d\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
155efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use deluxe scaling: %d\n",pcbddc->use_deluxe_scaling);CHKERRQ(ierr);
156efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use deluxe zerorows: %d\n",pcbddc->deluxe_zerorows);CHKERRQ(ierr);
157efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use deluxe singlemat: %d\n",pcbddc->deluxe_singlemat);CHKERRQ(ierr);
158efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Rebuild interface graph for Schur principal minors: %d\n",pcbddc->sub_schurs_rebuild);CHKERRQ(ierr);
15950e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Number of dofs' layers for the computation of principal minors: %D\n",pcbddc->sub_schurs_layers);CHKERRQ(ierr);
160efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Use user CSR graph to compute successive layers: %d\n",pcbddc->sub_schurs_use_useradj);CHKERRQ(ierr);
161bd2a564bSStefano Zampini     if (pcbddc->adaptive_threshold[1] != pcbddc->adaptive_threshold[0]) {
162bd2a564bSStefano 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);
163bd2a564bSStefano Zampini     } else {
164bd2a564bSStefano 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);
165bd2a564bSStefano Zampini     }
16650e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Min constraints / connected component: %D\n",pcbddc->adaptive_nmin);CHKERRQ(ierr);
16750e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Max constraints / connected component: %D\n",pcbddc->adaptive_nmax);CHKERRQ(ierr);
168efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Invert exact Schur complement for adaptive selection: %d\n",pcbddc->sub_schurs_exact_schur);CHKERRQ(ierr);
169efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Symmetric computation of primal basis functions: %d\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
17050e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Num. Procs. to map coarse adjacency list: %D\n",pcbddc->coarse_adj_red);CHKERRQ(ierr);
17150e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Coarse eqs per proc (significant at the coarsest level): %D\n",pcbddc->coarse_eqs_per_proc);CHKERRQ(ierr);
1728361f951SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Detect disconnected: %d (filter %d)\n",pcbddc->detect_disconnected,pcbddc->detect_disconnected_filter);CHKERRQ(ierr);
173efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Benign subspace trick: %d (change explicit %d)\n",pcbddc->benign_saddle_point,pcbddc->benign_change_explicit);CHKERRQ(ierr);
174efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Benign subspace trick is active: %d\n",pcbddc->benign_have_null);CHKERRQ(ierr);
175efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Algebraic computation of no-net-flux %d\n",pcbddc->compute_nonetflux);CHKERRQ(ierr);
176b74ba07aSstefano_zampini     if (!pc->setupcalled) PetscFunctionReturn(0);
1776b78500eSPatrick Sanan 
178fbad9177SStefano Zampini     /* compute interface size */
179e9627c49SStefano Zampini     ierr = VecSet(pcis->vec1_B,1.0);CHKERRQ(ierr);
180e9627c49SStefano Zampini     ierr = MatCreateVecs(pc->pmat,&counter,0);CHKERRQ(ierr);
181e9627c49SStefano Zampini     ierr = VecSet(counter,0.0);CHKERRQ(ierr);
182e9627c49SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
183e9627c49SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
184e9627c49SStefano Zampini     ierr = VecSum(counter,&interface_size);CHKERRQ(ierr);
185e9627c49SStefano Zampini     ierr = VecDestroy(&counter);CHKERRQ(ierr);
186fbad9177SStefano Zampini 
187fbad9177SStefano Zampini     /* compute some statistics on the domain decomposition */
188e9627c49SStefano Zampini     gsum[0] = 1;
189fbad9177SStefano Zampini     gsum[1] = gsum[2] = gsum[3] = gsum[4] = gsum[5] = 0;
190e9627c49SStefano Zampini     loc[0]  = !!pcis->n;
191e9627c49SStefano Zampini     loc[1]  = pcis->n - pcis->n_B;
192e9627c49SStefano Zampini     loc[2]  = pcis->n_B;
193e9627c49SStefano Zampini     loc[3]  = pcbddc->local_primal_size;
194345ecf6cSStefano Zampini     loc[4]  = pcis->n;
195fbad9177SStefano Zampini     loc[5]  = pcbddc->n_local_subs > 0 ? pcbddc->n_local_subs : (pcis->n ? 1 : 0);
196fbad9177SStefano Zampini     loc[6]  = pcbddc->benign_n;
197fbad9177SStefano Zampini     ierr = MPI_Reduce(loc,gsum,6,MPIU_INT64,MPI_SUM,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
198fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = -1;
199fbad9177SStefano Zampini     ierr = MPI_Reduce(loc,gmax,6,MPIU_INT64,MPI_MAX,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
200fbad9177SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = loc[4] = loc[5] = PETSC_MAX_INT;
201fbad9177SStefano Zampini     ierr = MPI_Reduce(loc,gmin,6,MPIU_INT64,MPI_MIN,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
202fbad9177SStefano Zampini     ierr = MPI_Reduce(&loc[6],&totbenign,1,MPIU_INT64,MPI_SUM,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
203e9627c49SStefano Zampini     if (pcbddc->coarse_size) {
204e9627c49SStefano Zampini       ratio1 = pc->pmat->rmap->N/(1.*pcbddc->coarse_size);
205e9627c49SStefano Zampini       ratio2 = PetscRealPart(interface_size)/pcbddc->coarse_size;
206e9627c49SStefano Zampini     }
207efd4aadfSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  ********************************** STATISTICS AT LEVEL %d **********************************\n",pcbddc->current_level);CHKERRQ(ierr);
20850e0721cSStefano 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);
20950e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Coarsening ratios: all/coarse %D interface/coarse %D\n",(PetscInt)ratio1,(PetscInt)ratio2);CHKERRQ(ierr);
21050e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Active processes : %D\n",(PetscInt)gsum[0]);CHKERRQ(ierr);
21150e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Total subdomains : %D\n",(PetscInt)gsum[5]);CHKERRQ(ierr);
212345ecf6cSStefano Zampini     if (pcbddc->benign_have_null) {
21350e0721cSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"  Benign subs      : %D\n",(PetscInt)totbenign);CHKERRQ(ierr);
214345ecf6cSStefano Zampini     }
21550e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Dofs type        :\tMIN\tMAX\tMEAN\n");CHKERRQ(ierr);
21650e0721cSStefano 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);
21750e0721cSStefano 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);
21850e0721cSStefano 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);
21950e0721cSStefano 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);
22050e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  Local     subs   :\t%D\t%D\n"    ,(PetscInt)gmin[5],(PetscInt)gmax[5]);CHKERRQ(ierr);
22150e0721cSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  ********************************** COARSE PROBLEM DETAILS *********************************\n");CHKERRQ(ierr);
22227b6a85dSStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
223e9627c49SStefano Zampini 
224fbad9177SStefano Zampini     /* the coarse problem can be handled by a different communicator */
225e9627c49SStefano Zampini     if (pcbddc->coarse_ksp) color = 1;
226e9627c49SStefano Zampini     else color = 0;
227e9627c49SStefano Zampini     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
2284b2aedd3SStefano Zampini     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
229e9627c49SStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)pc),&subcomm);CHKERRQ(ierr);
2304b2aedd3SStefano Zampini     ierr = PetscSubcommSetNumber(subcomm,PetscMin(size,2));CHKERRQ(ierr);
231e9627c49SStefano Zampini     ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
232e9627c49SStefano Zampini     ierr = PetscViewerGetSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer);CHKERRQ(ierr);
233e9627c49SStefano Zampini     if (color == 1) {
234e9627c49SStefano Zampini       ierr = KSPView(pcbddc->coarse_ksp,subviewer);CHKERRQ(ierr);
235e9627c49SStefano Zampini       ierr = PetscViewerFlush(subviewer);CHKERRQ(ierr);
236e9627c49SStefano Zampini     }
237e9627c49SStefano Zampini     ierr = PetscViewerRestoreSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer);CHKERRQ(ierr);
238e9627c49SStefano Zampini     ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
239e9627c49SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
240e9627c49SStefano Zampini   }
2416b78500eSPatrick Sanan   PetscFunctionReturn(0);
2426b78500eSPatrick Sanan }
243a13144ffSStefano Zampini 
2441e0482f5SStefano Zampini static PetscErrorCode PCBDDCSetDiscreteGradient_BDDC(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
245a13144ffSStefano Zampini {
246a13144ffSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
247a13144ffSStefano Zampini   PetscErrorCode ierr;
248a13144ffSStefano Zampini 
249a13144ffSStefano Zampini   PetscFunctionBegin;
250a13144ffSStefano Zampini   ierr = PetscObjectReference((PetscObject)G);CHKERRQ(ierr);
251a13144ffSStefano Zampini   ierr = MatDestroy(&pcbddc->discretegradient);CHKERRQ(ierr);
252a13144ffSStefano Zampini   pcbddc->discretegradient = G;
253a13144ffSStefano Zampini   pcbddc->nedorder         = order > 0 ? order : -order;
254495a2a07SStefano Zampini   pcbddc->nedfield         = field;
2551e0482f5SStefano Zampini   pcbddc->nedglobal        = global;
2561e0482f5SStefano Zampini   pcbddc->conforming       = conforming;
257a13144ffSStefano Zampini   PetscFunctionReturn(0);
258a13144ffSStefano Zampini }
259a13144ffSStefano Zampini 
260a13144ffSStefano Zampini /*@
261a13144ffSStefano Zampini  PCBDDCSetDiscreteGradient - Sets the discrete gradient
262a13144ffSStefano Zampini 
263a13144ffSStefano Zampini    Collective on PC
264a13144ffSStefano Zampini 
265a13144ffSStefano Zampini    Input Parameters:
266a13144ffSStefano Zampini +  pc         - the preconditioning context
267a13144ffSStefano Zampini .  G          - the discrete gradient matrix (should be in AIJ format)
268a13144ffSStefano Zampini .  order      - the order of the Nedelec space (1 for the lowest order)
269495a2a07SStefano Zampini .  field      - the field id of the Nedelec dofs (not used if the fields have not been specified)
2701e0482f5SStefano Zampini .  global     - the type of global ordering for the rows of G
271a13144ffSStefano Zampini -  conforming - whether the mesh is conforming or not
272a13144ffSStefano Zampini 
273a13144ffSStefano Zampini    Level: advanced
274a13144ffSStefano Zampini 
27595452b02SPatrick Sanan    Notes:
27695452b02SPatrick Sanan     The discrete gradient matrix G is used to analyze the subdomain edges, and it should not contain any zero entry.
277495a2a07SStefano Zampini           For variable order spaces, the order should be set to zero.
2781e0482f5SStefano Zampini           If global is true, the rows of G should be given in global ordering for the whole dofs;
2791e0482f5SStefano Zampini           if false, the ordering should be global for the Nedelec field.
2801e0482f5SStefano 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
2811e0482f5SStefano Zampini           and geid the one for the Nedelec field.
282a13144ffSStefano Zampini 
283495a2a07SStefano Zampini .seealso: PCBDDC,PCBDDCSetDofsSplitting(),PCBDDCSetDofsSplittingLocal()
284a13144ffSStefano Zampini @*/
2851e0482f5SStefano Zampini PetscErrorCode PCBDDCSetDiscreteGradient(PC pc, Mat G, PetscInt order, PetscInt field, PetscBool global, PetscBool conforming)
286a13144ffSStefano Zampini {
287a13144ffSStefano Zampini   PetscErrorCode ierr;
288a13144ffSStefano Zampini 
289a13144ffSStefano Zampini   PetscFunctionBegin;
290a13144ffSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
291a13144ffSStefano Zampini   PetscValidHeaderSpecific(G,MAT_CLASSID,2);
292a13144ffSStefano Zampini   PetscValidLogicalCollectiveInt(pc,order,3);
2931e0482f5SStefano Zampini   PetscValidLogicalCollectiveInt(pc,field,4);
2941e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc,global,5);
2951e0482f5SStefano Zampini   PetscValidLogicalCollectiveBool(pc,conforming,6);
2961e0482f5SStefano Zampini   PetscCheckSameComm(pc,1,G,2);
2971e0482f5SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDiscreteGradient_C",(PC,Mat,PetscInt,PetscInt,PetscBool,PetscBool),(pc,G,order,field,global,conforming));CHKERRQ(ierr);
298a13144ffSStefano Zampini   PetscFunctionReturn(0);
299a13144ffSStefano Zampini }
300a13144ffSStefano Zampini 
3018ae0ca82SStefano Zampini static PetscErrorCode PCBDDCSetDivergenceMat_BDDC(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
302a198735bSStefano Zampini {
303a198735bSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
304a198735bSStefano Zampini   PetscErrorCode ierr;
3056b78500eSPatrick Sanan 
306a198735bSStefano Zampini   PetscFunctionBegin;
307a198735bSStefano Zampini   ierr = PetscObjectReference((PetscObject)divudotp);CHKERRQ(ierr);
308a198735bSStefano Zampini   ierr = MatDestroy(&pcbddc->divudotp);CHKERRQ(ierr);
309a198735bSStefano Zampini   pcbddc->divudotp = divudotp;
3108ae0ca82SStefano Zampini   pcbddc->divudotp_trans = trans;
311a198735bSStefano Zampini   pcbddc->compute_nonetflux = PETSC_TRUE;
312a198735bSStefano Zampini   if (vl2l) {
313a198735bSStefano Zampini     ierr = PetscObjectReference((PetscObject)vl2l);CHKERRQ(ierr);
314fa23a32eSStefano Zampini     ierr = ISDestroy(&pcbddc->divudotp_vl2l);CHKERRQ(ierr);
315a198735bSStefano Zampini     pcbddc->divudotp_vl2l = vl2l;
316a198735bSStefano Zampini   }
317a198735bSStefano Zampini   PetscFunctionReturn(0);
318a198735bSStefano Zampini }
3193d996552SStefano Zampini 
320a198735bSStefano Zampini /*@
321a198735bSStefano Zampini  PCBDDCSetDivergenceMat - Sets the linear operator representing \int_\Omega \div {\bf u} \cdot p dx
322a198735bSStefano Zampini 
323a198735bSStefano Zampini    Collective on PC
324a198735bSStefano Zampini 
325a198735bSStefano Zampini    Input Parameters:
326a198735bSStefano Zampini +  pc - the preconditioning context
327a198735bSStefano Zampini .  divudotp - the matrix (must be of type MATIS)
3288ae0ca82SStefano Zampini .  trans - if trans if false (resp. true), then pressures are in the test (trial) space and velocities are in the trial (test) space.
32905a3bf82SStefano 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
330a198735bSStefano Zampini 
331a198735bSStefano Zampini    Level: advanced
332a198735bSStefano Zampini 
33395452b02SPatrick Sanan    Notes:
33495452b02SPatrick Sanan     This auxiliary matrix is used to compute quadrature weights representing the net-flux across subdomain boundaries
33505a3bf82SStefano Zampini           If vl2l is NULL, the local ordering for velocities in divudotp should match that of the preconditioning matrix
336a198735bSStefano Zampini 
337a198735bSStefano Zampini .seealso: PCBDDC
338a198735bSStefano Zampini @*/
3398ae0ca82SStefano Zampini PetscErrorCode PCBDDCSetDivergenceMat(PC pc, Mat divudotp, PetscBool trans, IS vl2l)
340a198735bSStefano Zampini {
341a198735bSStefano Zampini   PetscBool      ismatis;
342a198735bSStefano Zampini   PetscErrorCode ierr;
343a198735bSStefano Zampini 
344a198735bSStefano Zampini   PetscFunctionBegin;
345a198735bSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
346a198735bSStefano Zampini   PetscValidHeaderSpecific(divudotp,MAT_CLASSID,2);
347a198735bSStefano Zampini   PetscCheckSameComm(pc,1,divudotp,2);
3488ae0ca82SStefano Zampini   PetscValidLogicalCollectiveBool(pc,trans,3);
3498ae0ca82SStefano Zampini   if (vl2l) PetscValidHeaderSpecific(divudotp,IS_CLASSID,4);
350a198735bSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)divudotp,MATIS,&ismatis);CHKERRQ(ierr);
351a198735bSStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Divergence matrix needs to be of type MATIS");
3528ae0ca82SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDivergenceMat_C",(PC,Mat,PetscBool,IS),(pc,divudotp,trans,vl2l));CHKERRQ(ierr);
353a198735bSStefano Zampini   PetscFunctionReturn(0);
354a198735bSStefano Zampini }
3552d505d7fSStefano Zampini 
3561dd7afcfSStefano Zampini static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change, PetscBool interior)
357b9b85e73SStefano Zampini {
358b9b85e73SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
359b9b85e73SStefano Zampini   PetscErrorCode ierr;
360b9b85e73SStefano Zampini 
361b9b85e73SStefano Zampini   PetscFunctionBegin;
362b9b85e73SStefano Zampini   ierr = PetscObjectReference((PetscObject)change);CHKERRQ(ierr);
36356282151SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
364b9b85e73SStefano Zampini   pcbddc->user_ChangeOfBasisMatrix = change;
3651dd7afcfSStefano Zampini   pcbddc->change_interior = interior;
366b9b85e73SStefano Zampini   PetscFunctionReturn(0);
367b9b85e73SStefano Zampini }
368b9b85e73SStefano Zampini /*@
369906d46d4SStefano Zampini  PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs
370b9b85e73SStefano Zampini 
371b9b85e73SStefano Zampini    Collective on PC
372b9b85e73SStefano Zampini 
373b9b85e73SStefano Zampini    Input Parameters:
374b9b85e73SStefano Zampini +  pc - the preconditioning context
3751dd7afcfSStefano Zampini .  change - the change of basis matrix
3761dd7afcfSStefano Zampini -  interior - whether or not the change of basis modifies interior dofs
377b9b85e73SStefano Zampini 
378b9b85e73SStefano Zampini    Level: intermediate
379b9b85e73SStefano Zampini 
380b9b85e73SStefano Zampini    Notes:
381b9b85e73SStefano Zampini 
382b9b85e73SStefano Zampini .seealso: PCBDDC
383b9b85e73SStefano Zampini @*/
3841dd7afcfSStefano Zampini PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change, PetscBool interior)
385b9b85e73SStefano Zampini {
386b9b85e73SStefano Zampini   PetscErrorCode ierr;
387b9b85e73SStefano Zampini 
388b9b85e73SStefano Zampini   PetscFunctionBegin;
389b9b85e73SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
390b9b85e73SStefano Zampini   PetscValidHeaderSpecific(change,MAT_CLASSID,2);
391906d46d4SStefano Zampini   PetscCheckSameComm(pc,1,change,2);
392906d46d4SStefano Zampini   if (pc->mat) {
393906d46d4SStefano Zampini     PetscInt rows_c,cols_c,rows,cols;
394906d46d4SStefano Zampini     ierr = MatGetSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
395906d46d4SStefano Zampini     ierr = MatGetSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
396e0fe2d75SToby 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);
397e0fe2d75SToby 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);
398906d46d4SStefano Zampini     ierr = MatGetLocalSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
399906d46d4SStefano Zampini     ierr = MatGetLocalSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
400e0fe2d75SToby 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);
401e0fe2d75SToby 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);
402906d46d4SStefano Zampini   }
4031dd7afcfSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetChangeOfBasisMat_C",(PC,Mat,PetscBool),(pc,change,interior));CHKERRQ(ierr);
404b9b85e73SStefano Zampini   PetscFunctionReturn(0);
405b9b85e73SStefano Zampini }
4062d505d7fSStefano Zampini 
40730368db7SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesIS_BDDC(PC pc, IS PrimalVertices)
40830368db7SStefano Zampini {
40930368db7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
41056282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
41130368db7SStefano Zampini   PetscErrorCode ierr;
41230368db7SStefano Zampini 
41330368db7SStefano Zampini   PetscFunctionBegin;
41456282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
41556282151SStefano Zampini   if (pcbddc->user_primal_vertices) {
41656282151SStefano Zampini     ierr = ISEqual(PrimalVertices,pcbddc->user_primal_vertices,&isequal);CHKERRQ(ierr);
41756282151SStefano Zampini   }
41830368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
41930368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
42030368db7SStefano Zampini   pcbddc->user_primal_vertices = PrimalVertices;
42156282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
42230368db7SStefano Zampini   PetscFunctionReturn(0);
42330368db7SStefano Zampini }
424ab8c8b98SStefano Zampini 
42530368db7SStefano Zampini /*@
42630368db7SStefano Zampini  PCBDDCSetPrimalVerticesIS - Set additional user defined primal vertices in PCBDDC
42730368db7SStefano Zampini 
42830368db7SStefano Zampini    Collective
42930368db7SStefano Zampini 
43030368db7SStefano Zampini    Input Parameters:
43130368db7SStefano Zampini +  pc - the preconditioning context
43230368db7SStefano Zampini -  PrimalVertices - index set of primal vertices in global numbering (can be empty)
43330368db7SStefano Zampini 
43430368db7SStefano Zampini    Level: intermediate
43530368db7SStefano Zampini 
43630368db7SStefano Zampini    Notes:
43730368db7SStefano Zampini      Any process can list any global node
43830368db7SStefano Zampini 
43930368db7SStefano Zampini .seealso: PCBDDC
44030368db7SStefano Zampini @*/
44130368db7SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesIS(PC pc, IS PrimalVertices)
44230368db7SStefano Zampini {
44330368db7SStefano Zampini   PetscErrorCode ierr;
44430368db7SStefano Zampini 
44530368db7SStefano Zampini   PetscFunctionBegin;
44630368db7SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
44730368db7SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
44830368db7SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
44930368db7SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
45030368db7SStefano Zampini   PetscFunctionReturn(0);
45130368db7SStefano Zampini }
4522d505d7fSStefano Zampini 
453674ae819SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
454674ae819SStefano Zampini {
455674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
45656282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
457674ae819SStefano Zampini   PetscErrorCode ierr;
4581e6b0712SBarry Smith 
459674ae819SStefano Zampini   PetscFunctionBegin;
46056282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
46156282151SStefano Zampini   if (pcbddc->user_primal_vertices_local) {
46256282151SStefano Zampini     ierr = ISEqual(PrimalVertices,pcbddc->user_primal_vertices_local,&isequal);CHKERRQ(ierr);
46356282151SStefano Zampini   }
464674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
46530368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
46630368db7SStefano Zampini   pcbddc->user_primal_vertices_local = PrimalVertices;
46756282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
468674ae819SStefano Zampini   PetscFunctionReturn(0);
469674ae819SStefano Zampini }
470674ae819SStefano Zampini /*@
47128509bceSStefano Zampini  PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in PCBDDC
472674ae819SStefano Zampini 
47317eb1463SStefano Zampini    Collective
474674ae819SStefano Zampini 
475674ae819SStefano Zampini    Input Parameters:
476674ae819SStefano Zampini +  pc - the preconditioning context
47717eb1463SStefano Zampini -  PrimalVertices - index set of primal vertices in local numbering (can be empty)
478674ae819SStefano Zampini 
479674ae819SStefano Zampini    Level: intermediate
480674ae819SStefano Zampini 
481674ae819SStefano Zampini    Notes:
482674ae819SStefano Zampini 
483674ae819SStefano Zampini .seealso: PCBDDC
484674ae819SStefano Zampini @*/
485674ae819SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
486674ae819SStefano Zampini {
487674ae819SStefano Zampini   PetscErrorCode ierr;
488674ae819SStefano Zampini 
489674ae819SStefano Zampini   PetscFunctionBegin;
490674ae819SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
491674ae819SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
49217eb1463SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
493674ae819SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
494674ae819SStefano Zampini   PetscFunctionReturn(0);
495674ae819SStefano Zampini }
4962d505d7fSStefano Zampini 
4974fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k)
4984fad6a16SStefano Zampini {
4994fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
5004fad6a16SStefano Zampini 
5014fad6a16SStefano Zampini   PetscFunctionBegin;
5024fad6a16SStefano Zampini   pcbddc->coarsening_ratio = k;
5034fad6a16SStefano Zampini   PetscFunctionReturn(0);
5044fad6a16SStefano Zampini }
5051e6b0712SBarry Smith 
5064fad6a16SStefano Zampini /*@
50728509bceSStefano Zampini  PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel
5084fad6a16SStefano Zampini 
5094fad6a16SStefano Zampini    Logically collective on PC
5104fad6a16SStefano Zampini 
5114fad6a16SStefano Zampini    Input Parameters:
5124fad6a16SStefano Zampini +  pc - the preconditioning context
51328509bceSStefano Zampini -  k - coarsening ratio (H/h at the coarser level)
5144fad6a16SStefano Zampini 
5150f202f7eSStefano Zampini    Options Database Keys:
5160f202f7eSStefano Zampini .    -pc_bddc_coarsening_ratio
5174fad6a16SStefano Zampini 
5184fad6a16SStefano Zampini    Level: intermediate
5194fad6a16SStefano Zampini 
5204fad6a16SStefano Zampini    Notes:
5210f202f7eSStefano Zampini      Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level
5224fad6a16SStefano Zampini 
5230f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetLevels()
5244fad6a16SStefano Zampini @*/
5254fad6a16SStefano Zampini PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k)
5264fad6a16SStefano Zampini {
5274fad6a16SStefano Zampini   PetscErrorCode ierr;
5284fad6a16SStefano Zampini 
5294fad6a16SStefano Zampini   PetscFunctionBegin;
5304fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5312b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,k,2);
5324fad6a16SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));CHKERRQ(ierr);
5334fad6a16SStefano Zampini   PetscFunctionReturn(0);
5344fad6a16SStefano Zampini }
5352b510759SStefano Zampini 
536b8ffe317SStefano Zampini /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */
537b8ffe317SStefano Zampini static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc,PetscBool flg)
538b8ffe317SStefano Zampini {
539b8ffe317SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
540b8ffe317SStefano Zampini 
541b8ffe317SStefano Zampini   PetscFunctionBegin;
54285c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = flg;
543b8ffe317SStefano Zampini   PetscFunctionReturn(0);
544b8ffe317SStefano Zampini }
545b8ffe317SStefano Zampini 
546b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool flg)
5472b510759SStefano Zampini {
5482b510759SStefano Zampini   PetscErrorCode ierr;
5492b510759SStefano Zampini 
5502b510759SStefano Zampini   PetscFunctionBegin;
5512b510759SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
552b8ffe317SStefano Zampini   PetscValidLogicalCollectiveBool(pc,flg,2);
553b8ffe317SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetUseExactDirichlet_C",(PC,PetscBool),(pc,flg));CHKERRQ(ierr);
5542b510759SStefano Zampini   PetscFunctionReturn(0);
5552b510759SStefano Zampini }
5561e6b0712SBarry Smith 
5572b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc,PetscInt level)
5584fad6a16SStefano Zampini {
5594fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
5604fad6a16SStefano Zampini 
5614fad6a16SStefano Zampini   PetscFunctionBegin;
5622b510759SStefano Zampini   pcbddc->current_level = level;
5634fad6a16SStefano Zampini   PetscFunctionReturn(0);
5644fad6a16SStefano Zampini }
5651e6b0712SBarry Smith 
566b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level)
567b8ffe317SStefano Zampini {
568b8ffe317SStefano Zampini   PetscErrorCode ierr;
569b8ffe317SStefano Zampini 
570b8ffe317SStefano Zampini   PetscFunctionBegin;
571b8ffe317SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
572b8ffe317SStefano Zampini   PetscValidLogicalCollectiveInt(pc,level,2);
573b8ffe317SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLevel_C",(PC,PetscInt),(pc,level));CHKERRQ(ierr);
574b8ffe317SStefano Zampini   PetscFunctionReturn(0);
575b8ffe317SStefano Zampini }
576b8ffe317SStefano Zampini 
5772b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc,PetscInt levels)
5782b510759SStefano Zampini {
5792b510759SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
5802b510759SStefano Zampini 
5812b510759SStefano Zampini   PetscFunctionBegin;
5822b510759SStefano Zampini   pcbddc->max_levels = levels;
5832b510759SStefano Zampini   PetscFunctionReturn(0);
5842b510759SStefano Zampini }
5852b510759SStefano Zampini 
5864fad6a16SStefano Zampini /*@
587*37ebbdf7SStefano Zampini  PCBDDCSetLevels - Sets the maximum number of additional levels allowed for multilevel BDDC
5884fad6a16SStefano Zampini 
5894fad6a16SStefano Zampini    Logically collective on PC
5904fad6a16SStefano Zampini 
5914fad6a16SStefano Zampini    Input Parameters:
5924fad6a16SStefano Zampini +  pc - the preconditioning context
593*37ebbdf7SStefano Zampini -  levels - the maximum number of levels
5944fad6a16SStefano Zampini 
5950f202f7eSStefano Zampini    Options Database Keys:
5960f202f7eSStefano Zampini .    -pc_bddc_levels
5974fad6a16SStefano Zampini 
5984fad6a16SStefano Zampini    Level: intermediate
5994fad6a16SStefano Zampini 
6004fad6a16SStefano Zampini    Notes:
601*37ebbdf7SStefano Zampini      The default value is 0, that gives the classical two-levels BDDC
6024fad6a16SStefano Zampini 
6030f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetCoarseningRatio()
6044fad6a16SStefano Zampini @*/
6052b510759SStefano Zampini PetscErrorCode PCBDDCSetLevels(PC pc,PetscInt levels)
6064fad6a16SStefano Zampini {
6074fad6a16SStefano Zampini   PetscErrorCode ierr;
6084fad6a16SStefano Zampini 
6094fad6a16SStefano Zampini   PetscFunctionBegin;
6104fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
6112b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,levels,2);
612*37ebbdf7SStefano 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);
6132b510759SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLevels_C",(PC,PetscInt),(pc,levels));CHKERRQ(ierr);
6144fad6a16SStefano Zampini   PetscFunctionReturn(0);
6154fad6a16SStefano Zampini }
6161e6b0712SBarry Smith 
6173b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
6183b03a366Sstefano_zampini {
6193b03a366Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
62056282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
6213b03a366Sstefano_zampini   PetscErrorCode ierr;
6223b03a366Sstefano_zampini 
6233b03a366Sstefano_zampini   PetscFunctionBegin;
62456282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
62556282151SStefano Zampini   if (pcbddc->DirichletBoundaries) {
62656282151SStefano Zampini     ierr = ISEqual(DirichletBoundaries,pcbddc->DirichletBoundaries,&isequal);CHKERRQ(ierr);
62756282151SStefano Zampini   }
628785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
629785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
6303b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
63136e030ebSStefano Zampini   pcbddc->DirichletBoundaries = DirichletBoundaries;
63256282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
6333b03a366Sstefano_zampini   PetscFunctionReturn(0);
6343b03a366Sstefano_zampini }
6351e6b0712SBarry Smith 
6363b03a366Sstefano_zampini /*@
63728509bceSStefano Zampini  PCBDDCSetDirichletBoundaries - Set IS defining Dirichlet boundaries for the global problem.
6383b03a366Sstefano_zampini 
639785d1243SStefano Zampini    Collective
6403b03a366Sstefano_zampini 
6413b03a366Sstefano_zampini    Input Parameters:
6423b03a366Sstefano_zampini +  pc - the preconditioning context
643785d1243SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries
6443b03a366Sstefano_zampini 
6453b03a366Sstefano_zampini    Level: intermediate
6463b03a366Sstefano_zampini 
6470f202f7eSStefano Zampini    Notes:
6480f202f7eSStefano Zampini      Provide the information if you used MatZeroRows/Columns routines. Any process can list any global node
6493b03a366Sstefano_zampini 
6500f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetDirichletBoundariesLocal(), MatZeroRows(), MatZeroRowsColumns()
6513b03a366Sstefano_zampini @*/
6523b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
6533b03a366Sstefano_zampini {
6543b03a366Sstefano_zampini   PetscErrorCode ierr;
6553b03a366Sstefano_zampini 
6563b03a366Sstefano_zampini   PetscFunctionBegin;
6573b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
658674ae819SStefano Zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
659785d1243SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
6603b03a366Sstefano_zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
6613b03a366Sstefano_zampini   PetscFunctionReturn(0);
6623b03a366Sstefano_zampini }
6631e6b0712SBarry Smith 
66482ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc,IS DirichletBoundaries)
6653b03a366Sstefano_zampini {
6663b03a366Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
66756282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
6683b03a366Sstefano_zampini   PetscErrorCode ierr;
6693b03a366Sstefano_zampini 
6703b03a366Sstefano_zampini   PetscFunctionBegin;
67156282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
67256282151SStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
67356282151SStefano Zampini     ierr = ISEqual(DirichletBoundaries,pcbddc->DirichletBoundariesLocal,&isequal);CHKERRQ(ierr);
67456282151SStefano Zampini   }
675785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
676785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
6773b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
678785d1243SStefano Zampini   pcbddc->DirichletBoundariesLocal = DirichletBoundaries;
67956282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
6803b03a366Sstefano_zampini   PetscFunctionReturn(0);
6813b03a366Sstefano_zampini }
6823b03a366Sstefano_zampini 
6833b03a366Sstefano_zampini /*@
68482ba6b80SStefano Zampini  PCBDDCSetDirichletBoundariesLocal - Set IS defining Dirichlet boundaries for the global problem in local ordering.
6853b03a366Sstefano_zampini 
686785d1243SStefano Zampini    Collective
6873b03a366Sstefano_zampini 
6883b03a366Sstefano_zampini    Input Parameters:
6893b03a366Sstefano_zampini +  pc - the preconditioning context
69082ba6b80SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries (in local ordering)
6913b03a366Sstefano_zampini 
6923b03a366Sstefano_zampini    Level: intermediate
6933b03a366Sstefano_zampini 
6943b03a366Sstefano_zampini    Notes:
6953b03a366Sstefano_zampini 
6960f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetDirichletBoundaries(), MatZeroRows(), MatZeroRowsColumns()
6973b03a366Sstefano_zampini @*/
69882ba6b80SStefano Zampini PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc,IS DirichletBoundaries)
6993b03a366Sstefano_zampini {
7003b03a366Sstefano_zampini   PetscErrorCode ierr;
7013b03a366Sstefano_zampini 
7023b03a366Sstefano_zampini   PetscFunctionBegin;
7033b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
7043b03a366Sstefano_zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
70582ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
70682ba6b80SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundariesLocal_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
7073b03a366Sstefano_zampini   PetscFunctionReturn(0);
7083b03a366Sstefano_zampini }
7093b03a366Sstefano_zampini 
71053cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
7110c7d97c5SJed Brown {
7120c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
71356282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
71453cdbc3dSStefano Zampini   PetscErrorCode ierr;
7150c7d97c5SJed Brown 
7160c7d97c5SJed Brown   PetscFunctionBegin;
71756282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
71856282151SStefano Zampini   if (pcbddc->NeumannBoundaries) {
71956282151SStefano Zampini     ierr = ISEqual(NeumannBoundaries,pcbddc->NeumannBoundaries,&isequal);CHKERRQ(ierr);
72056282151SStefano Zampini   }
721785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
722785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
72353cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
72436e030ebSStefano Zampini   pcbddc->NeumannBoundaries = NeumannBoundaries;
72556282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7260c7d97c5SJed Brown   PetscFunctionReturn(0);
7270c7d97c5SJed Brown }
7281e6b0712SBarry Smith 
72957527edcSJed Brown /*@
73028509bceSStefano Zampini  PCBDDCSetNeumannBoundaries - Set IS defining Neumann boundaries for the global problem.
73157527edcSJed Brown 
732785d1243SStefano Zampini    Collective
73357527edcSJed Brown 
73457527edcSJed Brown    Input Parameters:
73557527edcSJed Brown +  pc - the preconditioning context
736785d1243SStefano Zampini -  NeumannBoundaries - parallel IS defining the Neumann boundaries
73757527edcSJed Brown 
73857527edcSJed Brown    Level: intermediate
73957527edcSJed Brown 
7400f202f7eSStefano Zampini    Notes:
7410f202f7eSStefano Zampini      Any process can list any global node
74257527edcSJed Brown 
7430f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetNeumannBoundariesLocal()
74457527edcSJed Brown @*/
74553cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
7460c7d97c5SJed Brown {
7470c7d97c5SJed Brown   PetscErrorCode ierr;
7480c7d97c5SJed Brown 
7490c7d97c5SJed Brown   PetscFunctionBegin;
7500c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
751674ae819SStefano Zampini   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
752785d1243SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
75353cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
75453cdbc3dSStefano Zampini   PetscFunctionReturn(0);
75553cdbc3dSStefano Zampini }
7561e6b0712SBarry Smith 
75782ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc,IS NeumannBoundaries)
7580c7d97c5SJed Brown {
7590c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
76056282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
7610c7d97c5SJed Brown   PetscErrorCode ierr;
7620c7d97c5SJed Brown 
7630c7d97c5SJed Brown   PetscFunctionBegin;
76456282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
76556282151SStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
76656282151SStefano Zampini     ierr = ISEqual(NeumannBoundaries,pcbddc->NeumannBoundariesLocal,&isequal);CHKERRQ(ierr);
76756282151SStefano Zampini   }
768785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
769785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
7700c7d97c5SJed Brown   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
771785d1243SStefano Zampini   pcbddc->NeumannBoundariesLocal = NeumannBoundaries;
77256282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7730c7d97c5SJed Brown   PetscFunctionReturn(0);
7740c7d97c5SJed Brown }
7750c7d97c5SJed Brown 
7760c7d97c5SJed Brown /*@
77782ba6b80SStefano Zampini  PCBDDCSetNeumannBoundariesLocal - Set IS defining Neumann boundaries for the global problem in local ordering.
7780c7d97c5SJed Brown 
779785d1243SStefano Zampini    Collective
7800c7d97c5SJed Brown 
7810c7d97c5SJed Brown    Input Parameters:
7820c7d97c5SJed Brown +  pc - the preconditioning context
78382ba6b80SStefano Zampini -  NeumannBoundaries - parallel IS defining the subdomain part of Neumann boundaries (in local ordering)
7840c7d97c5SJed Brown 
7850c7d97c5SJed Brown    Level: intermediate
7860c7d97c5SJed Brown 
7870c7d97c5SJed Brown    Notes:
7880c7d97c5SJed Brown 
7890f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetNeumannBoundaries()
7900c7d97c5SJed Brown @*/
79182ba6b80SStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc,IS NeumannBoundaries)
7920c7d97c5SJed Brown {
7930c7d97c5SJed Brown   PetscErrorCode ierr;
7940c7d97c5SJed Brown 
7950c7d97c5SJed Brown   PetscFunctionBegin;
7960c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
7970c7d97c5SJed Brown   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
79882ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
79982ba6b80SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundariesLocal_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
80053cdbc3dSStefano Zampini   PetscFunctionReturn(0);
80153cdbc3dSStefano Zampini }
80253cdbc3dSStefano Zampini 
803da1bb401SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
804da1bb401SStefano Zampini {
805da1bb401SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
806da1bb401SStefano Zampini 
807da1bb401SStefano Zampini   PetscFunctionBegin;
808da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
809da1bb401SStefano Zampini   PetscFunctionReturn(0);
810da1bb401SStefano Zampini }
8111e6b0712SBarry Smith 
812da1bb401SStefano Zampini /*@
813785d1243SStefano Zampini  PCBDDCGetDirichletBoundaries - Get parallel IS for Dirichlet boundaries
814da1bb401SStefano Zampini 
815785d1243SStefano Zampini    Collective
816785d1243SStefano Zampini 
817785d1243SStefano Zampini    Input Parameters:
818785d1243SStefano Zampini .  pc - the preconditioning context
819785d1243SStefano Zampini 
820785d1243SStefano Zampini    Output Parameters:
821785d1243SStefano Zampini .  DirichletBoundaries - index set defining the Dirichlet boundaries
822785d1243SStefano Zampini 
823785d1243SStefano Zampini    Level: intermediate
824785d1243SStefano Zampini 
8250f202f7eSStefano Zampini    Notes:
8260f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetDirichletBoundaries
827785d1243SStefano Zampini 
828785d1243SStefano Zampini .seealso: PCBDDC
829785d1243SStefano Zampini @*/
830785d1243SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
831785d1243SStefano Zampini {
832785d1243SStefano Zampini   PetscErrorCode ierr;
833785d1243SStefano Zampini 
834785d1243SStefano Zampini   PetscFunctionBegin;
835785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
836785d1243SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
837785d1243SStefano Zampini   PetscFunctionReturn(0);
838785d1243SStefano Zampini }
839785d1243SStefano Zampini 
840785d1243SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc,IS *DirichletBoundaries)
841785d1243SStefano Zampini {
842785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
843785d1243SStefano Zampini 
844785d1243SStefano Zampini   PetscFunctionBegin;
845785d1243SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundariesLocal;
846785d1243SStefano Zampini   PetscFunctionReturn(0);
847785d1243SStefano Zampini }
848785d1243SStefano Zampini 
849da1bb401SStefano Zampini /*@
85082ba6b80SStefano Zampini  PCBDDCGetDirichletBoundariesLocal - Get parallel IS for Dirichlet boundaries (in local ordering)
851da1bb401SStefano Zampini 
852785d1243SStefano Zampini    Collective
853da1bb401SStefano Zampini 
854da1bb401SStefano Zampini    Input Parameters:
85528509bceSStefano Zampini .  pc - the preconditioning context
856da1bb401SStefano Zampini 
857da1bb401SStefano Zampini    Output Parameters:
85828509bceSStefano Zampini .  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
859da1bb401SStefano Zampini 
860da1bb401SStefano Zampini    Level: intermediate
861da1bb401SStefano Zampini 
862da1bb401SStefano Zampini    Notes:
8630f202f7eSStefano 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).
8640f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
865da1bb401SStefano Zampini 
866da1bb401SStefano Zampini .seealso: PCBDDC
867da1bb401SStefano Zampini @*/
86882ba6b80SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc,IS *DirichletBoundaries)
869da1bb401SStefano Zampini {
870da1bb401SStefano Zampini   PetscErrorCode ierr;
871da1bb401SStefano Zampini 
872da1bb401SStefano Zampini   PetscFunctionBegin;
873da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
87482ba6b80SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundariesLocal_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
875da1bb401SStefano Zampini   PetscFunctionReturn(0);
876da1bb401SStefano Zampini }
8771e6b0712SBarry Smith 
87853cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
87953cdbc3dSStefano Zampini {
88053cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
88153cdbc3dSStefano Zampini 
88253cdbc3dSStefano Zampini   PetscFunctionBegin;
88353cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
88453cdbc3dSStefano Zampini   PetscFunctionReturn(0);
88553cdbc3dSStefano Zampini }
8861e6b0712SBarry Smith 
88753cdbc3dSStefano Zampini /*@
888785d1243SStefano Zampini  PCBDDCGetNeumannBoundaries - Get parallel IS for Neumann boundaries
88953cdbc3dSStefano Zampini 
890785d1243SStefano Zampini    Collective
891785d1243SStefano Zampini 
892785d1243SStefano Zampini    Input Parameters:
893785d1243SStefano Zampini .  pc - the preconditioning context
894785d1243SStefano Zampini 
895785d1243SStefano Zampini    Output Parameters:
896785d1243SStefano Zampini .  NeumannBoundaries - index set defining the Neumann boundaries
897785d1243SStefano Zampini 
898785d1243SStefano Zampini    Level: intermediate
899785d1243SStefano Zampini 
9000f202f7eSStefano Zampini    Notes:
9010f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetNeumannBoundaries
902785d1243SStefano Zampini 
903785d1243SStefano Zampini .seealso: PCBDDC
904785d1243SStefano Zampini @*/
905785d1243SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
906785d1243SStefano Zampini {
907785d1243SStefano Zampini   PetscErrorCode ierr;
908785d1243SStefano Zampini 
909785d1243SStefano Zampini   PetscFunctionBegin;
910785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
911785d1243SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
912785d1243SStefano Zampini   PetscFunctionReturn(0);
913785d1243SStefano Zampini }
914785d1243SStefano Zampini 
915785d1243SStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc,IS *NeumannBoundaries)
916785d1243SStefano Zampini {
917785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
918785d1243SStefano Zampini 
919785d1243SStefano Zampini   PetscFunctionBegin;
920785d1243SStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundariesLocal;
921785d1243SStefano Zampini   PetscFunctionReturn(0);
922785d1243SStefano Zampini }
923785d1243SStefano Zampini 
92453cdbc3dSStefano Zampini /*@
92582ba6b80SStefano Zampini  PCBDDCGetNeumannBoundariesLocal - Get parallel IS for Neumann boundaries (in local ordering)
92653cdbc3dSStefano Zampini 
927785d1243SStefano Zampini    Collective
92853cdbc3dSStefano Zampini 
92953cdbc3dSStefano Zampini    Input Parameters:
93028509bceSStefano Zampini .  pc - the preconditioning context
93153cdbc3dSStefano Zampini 
93253cdbc3dSStefano Zampini    Output Parameters:
93328509bceSStefano Zampini .  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
93453cdbc3dSStefano Zampini 
93553cdbc3dSStefano Zampini    Level: intermediate
93653cdbc3dSStefano Zampini 
93753cdbc3dSStefano Zampini    Notes:
9380f202f7eSStefano 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).
9390f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
94053cdbc3dSStefano Zampini 
94153cdbc3dSStefano Zampini .seealso: PCBDDC
94253cdbc3dSStefano Zampini @*/
94382ba6b80SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc,IS *NeumannBoundaries)
94453cdbc3dSStefano Zampini {
94553cdbc3dSStefano Zampini   PetscErrorCode ierr;
94653cdbc3dSStefano Zampini 
94753cdbc3dSStefano Zampini   PetscFunctionBegin;
94853cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
94982ba6b80SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundariesLocal_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
9500c7d97c5SJed Brown   PetscFunctionReturn(0);
9510c7d97c5SJed Brown }
9521e6b0712SBarry Smith 
9531a83f524SJed Brown static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
95436e030ebSStefano Zampini {
95536e030ebSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
956da1bb401SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
95756282151SStefano Zampini   PetscBool      same_data = PETSC_FALSE;
958da1bb401SStefano Zampini   PetscErrorCode ierr;
95936e030ebSStefano Zampini 
96036e030ebSStefano Zampini   PetscFunctionBegin;
9618687889aSStefano Zampini   if (!nvtxs) {
96204194a47SStefano Zampini     if (copymode == PETSC_OWN_POINTER) {
96304194a47SStefano Zampini       ierr = PetscFree(xadj);CHKERRQ(ierr);
96404194a47SStefano Zampini       ierr = PetscFree(adjncy);CHKERRQ(ierr);
96504194a47SStefano Zampini     }
9668687889aSStefano Zampini     ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
9678687889aSStefano Zampini     PetscFunctionReturn(0);
9688687889aSStefano Zampini   }
96966da6bd7Sstefano_zampini   if (mat_graph->nvtxs == nvtxs && mat_graph->freecsr) { /* we own the data */
97056282151SStefano Zampini     if (mat_graph->xadj == xadj && mat_graph->adjncy == adjncy) same_data = PETSC_TRUE;
97156282151SStefano Zampini     if (!same_data && mat_graph->xadj[nvtxs] == xadj[nvtxs]) {
9722d505d7fSStefano Zampini       ierr = PetscMemcmp(xadj,mat_graph->xadj,(nvtxs+1)*sizeof(PetscInt),&same_data);CHKERRQ(ierr);
9732d505d7fSStefano Zampini       if (same_data) {
9742d505d7fSStefano Zampini         ierr = PetscMemcmp(adjncy,mat_graph->adjncy,xadj[nvtxs]*sizeof(PetscInt),&same_data);CHKERRQ(ierr);
9752d505d7fSStefano Zampini       }
97656282151SStefano Zampini     }
97756282151SStefano Zampini   }
97856282151SStefano Zampini   if (!same_data) {
979674ae819SStefano Zampini     /* free old CSR */
980674ae819SStefano Zampini     ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
981674ae819SStefano Zampini     /* get CSR into graph structure */
982da1bb401SStefano Zampini     if (copymode == PETSC_COPY_VALUES) {
983854ce69bSBarry Smith       ierr = PetscMalloc1(nvtxs+1,&mat_graph->xadj);CHKERRQ(ierr);
984785e854fSJed Brown       ierr = PetscMalloc1(xadj[nvtxs],&mat_graph->adjncy);CHKERRQ(ierr);
985674ae819SStefano Zampini       ierr = PetscMemcpy(mat_graph->xadj,xadj,(nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
986674ae819SStefano Zampini       ierr = PetscMemcpy(mat_graph->adjncy,adjncy,xadj[nvtxs]*sizeof(PetscInt));CHKERRQ(ierr);
987a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
988da1bb401SStefano Zampini     } else if (copymode == PETSC_OWN_POINTER) {
9891a83f524SJed Brown       mat_graph->xadj    = (PetscInt*)xadj;
9901a83f524SJed Brown       mat_graph->adjncy  = (PetscInt*)adjncy;
991a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_TRUE;
992a1dbd327SStefano Zampini     } else if (copymode == PETSC_USE_POINTER) {
993a1dbd327SStefano Zampini       mat_graph->xadj    = (PetscInt*)xadj;
994a1dbd327SStefano Zampini       mat_graph->adjncy  = (PetscInt*)adjncy;
995a1dbd327SStefano Zampini       mat_graph->freecsr = PETSC_FALSE;
996e0fe2d75SToby Isaac     } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %D",copymode);
997575ad6abSStefano Zampini     mat_graph->nvtxs_csr = nvtxs;
99856282151SStefano Zampini     pcbddc->recompute_topography = PETSC_TRUE;
99956282151SStefano Zampini   }
100036e030ebSStefano Zampini   PetscFunctionReturn(0);
100136e030ebSStefano Zampini }
10021e6b0712SBarry Smith 
100336e030ebSStefano Zampini /*@
100454fffbccSStefano Zampini  PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local degrees of freedom.
100536e030ebSStefano Zampini 
100636e030ebSStefano Zampini    Not collective
100736e030ebSStefano Zampini 
100836e030ebSStefano Zampini    Input Parameters:
100954fffbccSStefano Zampini +  pc - the preconditioning context.
101054fffbccSStefano Zampini .  nvtxs - number of local vertices of the graph (i.e., the number of local dofs).
101154fffbccSStefano Zampini .  xadj, adjncy - the connectivity of the dofs in CSR format.
101254fffbccSStefano Zampini -  copymode - supported modes are PETSC_COPY_VALUES, PETSC_USE_POINTER or PETSC_OWN_POINTER.
101336e030ebSStefano Zampini 
101436e030ebSStefano Zampini    Level: intermediate
101536e030ebSStefano Zampini 
101695452b02SPatrick Sanan    Notes:
101795452b02SPatrick Sanan     A dof is considered connected with all local dofs if xadj[dof+1]-xadj[dof] == 1 and adjncy[xadj[dof]] is negative.
101836e030ebSStefano Zampini 
101928509bceSStefano Zampini .seealso: PCBDDC,PetscCopyMode
102036e030ebSStefano Zampini @*/
10211a83f524SJed Brown PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
102236e030ebSStefano Zampini {
1023575ad6abSStefano Zampini   void (*f)(void) = 0;
102436e030ebSStefano Zampini   PetscErrorCode ierr;
102536e030ebSStefano Zampini 
102636e030ebSStefano Zampini   PetscFunctionBegin;
102736e030ebSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
10288687889aSStefano Zampini   if (nvtxs) {
1029674ae819SStefano Zampini     PetscValidIntPointer(xadj,3);
10301633d1f0SStefano Zampini     if (xadj[nvtxs]) PetscValidIntPointer(adjncy,4);
10318687889aSStefano Zampini   }
10321a83f524SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
1033575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
1034575ad6abSStefano Zampini   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr);
1035575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
1036575ad6abSStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
1037575ad6abSStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
1038da1bb401SStefano Zampini   }
103936e030ebSStefano Zampini   PetscFunctionReturn(0);
104036e030ebSStefano Zampini }
10411e6b0712SBarry Smith 
104263602bcaSStefano Zampini static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
104363602bcaSStefano Zampini {
104463602bcaSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
104563602bcaSStefano Zampini   PetscInt       i;
104656282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
104763602bcaSStefano Zampini   PetscErrorCode ierr;
104863602bcaSStefano Zampini 
104963602bcaSStefano Zampini   PetscFunctionBegin;
105056282151SStefano Zampini   if (pcbddc->n_ISForDofsLocal == n_is) {
105156282151SStefano Zampini     for (i=0;i<n_is;i++) {
105256282151SStefano Zampini       PetscBool isequalt;
105356282151SStefano Zampini       ierr = ISEqual(ISForDofs[i],pcbddc->ISForDofsLocal[i],&isequalt);CHKERRQ(ierr);
105456282151SStefano Zampini       if (!isequalt) break;
105556282151SStefano Zampini     }
105656282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
105756282151SStefano Zampini   }
105856282151SStefano Zampini   for (i=0;i<n_is;i++) {
105956282151SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
106056282151SStefano Zampini   }
106163602bcaSStefano Zampini   /* Destroy ISes if they were already set */
106263602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
106363602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
106463602bcaSStefano Zampini   }
106563602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
106663602bcaSStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
106763602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
106863602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
106963602bcaSStefano Zampini   }
107063602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
107163602bcaSStefano Zampini   pcbddc->n_ISForDofs = 0;
107263602bcaSStefano Zampini   /* allocate space then set */
1073d02579f5SStefano Zampini   if (n_is) {
1074d02579f5SStefano Zampini     ierr = PetscMalloc1(n_is,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
1075d02579f5SStefano Zampini   }
107663602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
107763602bcaSStefano Zampini     pcbddc->ISForDofsLocal[i] = ISForDofs[i];
107863602bcaSStefano Zampini   }
107963602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = n_is;
108063602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
108156282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
108263602bcaSStefano Zampini   PetscFunctionReturn(0);
108363602bcaSStefano Zampini }
108463602bcaSStefano Zampini 
108563602bcaSStefano Zampini /*@
108663602bcaSStefano Zampini  PCBDDCSetDofsSplittingLocal - Set index sets defining fields of the local subdomain matrix
108763602bcaSStefano Zampini 
108863602bcaSStefano Zampini    Collective
108963602bcaSStefano Zampini 
109063602bcaSStefano Zampini    Input Parameters:
109163602bcaSStefano Zampini +  pc - the preconditioning context
10920f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
10930f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in local ordering
109463602bcaSStefano Zampini 
109563602bcaSStefano Zampini    Level: intermediate
109663602bcaSStefano Zampini 
10970f202f7eSStefano Zampini    Notes:
10980f202f7eSStefano Zampini      n_is should be the same among processes. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
109963602bcaSStefano Zampini 
110063602bcaSStefano Zampini .seealso: PCBDDC
110163602bcaSStefano Zampini @*/
110263602bcaSStefano Zampini PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc,PetscInt n_is, IS ISForDofs[])
110363602bcaSStefano Zampini {
110463602bcaSStefano Zampini   PetscInt       i;
110563602bcaSStefano Zampini   PetscErrorCode ierr;
110663602bcaSStefano Zampini 
110763602bcaSStefano Zampini   PetscFunctionBegin;
110863602bcaSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
110963602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
111063602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
111163602bcaSStefano Zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
111263602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
111363602bcaSStefano Zampini   }
1114e71e7a71SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplittingLocal_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
111563602bcaSStefano Zampini   PetscFunctionReturn(0);
111663602bcaSStefano Zampini }
111763602bcaSStefano Zampini 
11189c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
11199c0446d6SStefano Zampini {
11209c0446d6SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
11219c0446d6SStefano Zampini   PetscInt       i;
112256282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
11239c0446d6SStefano Zampini   PetscErrorCode ierr;
11249c0446d6SStefano Zampini 
11259c0446d6SStefano Zampini   PetscFunctionBegin;
112656282151SStefano Zampini   if (pcbddc->n_ISForDofs == n_is) {
112756282151SStefano Zampini     for (i=0;i<n_is;i++) {
112856282151SStefano Zampini       PetscBool isequalt;
112956282151SStefano Zampini       ierr = ISEqual(ISForDofs[i],pcbddc->ISForDofs[i],&isequalt);CHKERRQ(ierr);
113056282151SStefano Zampini       if (!isequalt) break;
113156282151SStefano Zampini     }
113256282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
113356282151SStefano Zampini   }
113456282151SStefano Zampini   for (i=0;i<n_is;i++) {
113556282151SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
113656282151SStefano Zampini   }
1137da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
11389c0446d6SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
11399c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
11409c0446d6SStefano Zampini   }
1141d11ae9bbSstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
114263602bcaSStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
114363602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
114463602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
114563602bcaSStefano Zampini   }
114663602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
114763602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = 0;
1148da1bb401SStefano Zampini   /* allocate space then set */
1149d02579f5SStefano Zampini   if (n_is) {
1150785e854fSJed Brown     ierr = PetscMalloc1(n_is,&pcbddc->ISForDofs);CHKERRQ(ierr);
1151d02579f5SStefano Zampini   }
11529c0446d6SStefano Zampini   for (i=0;i<n_is;i++) {
1153da1bb401SStefano Zampini     pcbddc->ISForDofs[i] = ISForDofs[i];
11549c0446d6SStefano Zampini   }
11559c0446d6SStefano Zampini   pcbddc->n_ISForDofs = n_is;
115663602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
115756282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
11589c0446d6SStefano Zampini   PetscFunctionReturn(0);
11599c0446d6SStefano Zampini }
11601e6b0712SBarry Smith 
11619c0446d6SStefano Zampini /*@
116263602bcaSStefano Zampini  PCBDDCSetDofsSplitting - Set index sets defining fields of the global matrix
11639c0446d6SStefano Zampini 
116463602bcaSStefano Zampini    Collective
11659c0446d6SStefano Zampini 
11669c0446d6SStefano Zampini    Input Parameters:
11679c0446d6SStefano Zampini +  pc - the preconditioning context
11680f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
11690f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in global ordering
11709c0446d6SStefano Zampini 
11719c0446d6SStefano Zampini    Level: intermediate
11729c0446d6SStefano Zampini 
11730f202f7eSStefano Zampini    Notes:
11740f202f7eSStefano Zampini      Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
11759c0446d6SStefano Zampini 
11769c0446d6SStefano Zampini .seealso: PCBDDC
11779c0446d6SStefano Zampini @*/
11789c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
11799c0446d6SStefano Zampini {
11802b510759SStefano Zampini   PetscInt       i;
11819c0446d6SStefano Zampini   PetscErrorCode ierr;
11829c0446d6SStefano Zampini 
11839c0446d6SStefano Zampini   PetscFunctionBegin;
11849c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
118563602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
11862b510759SStefano Zampini   for (i=0;i<n_is;i++) {
118763602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
1188a011d5a7Sstefano_zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
11892b510759SStefano Zampini   }
11909c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
11919c0446d6SStefano Zampini   PetscFunctionReturn(0);
11929c0446d6SStefano Zampini }
1193906d46d4SStefano Zampini 
1194534831adSStefano Zampini /*
1195534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
1196534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
11979c0446d6SStefano Zampini 
1198534831adSStefano Zampini    Input Parameter:
1199534831adSStefano Zampini +  pc - the preconditioner contex
1200534831adSStefano Zampini 
1201534831adSStefano Zampini    Application Interface Routine: PCPreSolve()
1202534831adSStefano Zampini 
1203534831adSStefano Zampini    Notes:
1204534831adSStefano Zampini      The interface routine PCPreSolve() is not usually called directly by
1205534831adSStefano Zampini    the user, but instead is called by KSPSolve().
1206534831adSStefano Zampini */
1207534831adSStefano Zampini static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1208534831adSStefano Zampini {
1209534831adSStefano Zampini   PetscErrorCode ierr;
1210534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1211534831adSStefano Zampini   PC_IS          *pcis = (PC_IS*)(pc->data);
12123972b0daSStefano Zampini   Vec            used_vec;
121327b6a85dSStefano Zampini   PetscBool      save_rhs = PETSC_TRUE, benign_correction_computed;
1214534831adSStefano Zampini 
1215534831adSStefano Zampini   PetscFunctionBegin;
12161f4df5f7SStefano Zampini   /* if we are working with CG, one dirichlet solve can be avoided during Krylov iterations */
121785c4d303SStefano Zampini   if (ksp) {
12181f4df5f7SStefano Zampini     PetscBool iscg, isgroppcg, ispipecg, ispipecgrr;
121985c4d303SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPCG,&iscg);CHKERRQ(ierr);
122027b6a85dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPGROPPCG,&isgroppcg);CHKERRQ(ierr);
122127b6a85dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECG,&ispipecg);CHKERRQ(ierr);
1222f94e96cbSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECGRR,&ispipecgrr);CHKERRQ(ierr);
12231f4df5f7SStefano Zampini     if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static || (!iscg && !isgroppcg && !ispipecg && !ispipecgrr)) {
122485c4d303SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
122585c4d303SStefano Zampini     }
122685c4d303SStefano Zampini   }
1227fc17d649SStefano Zampini   if (pcbddc->benign_apply_coarse_only || pcbddc->switch_static) {
1228fc17d649SStefano Zampini     ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
1229fc17d649SStefano Zampini   }
12301f4df5f7SStefano Zampini 
123185c4d303SStefano Zampini   /* Creates parallel work vectors used in presolve */
123262a6ff1dSStefano Zampini   if (!pcbddc->original_rhs) {
123362a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
123462a6ff1dSStefano Zampini   }
123562a6ff1dSStefano Zampini   if (!pcbddc->temp_solution) {
123662a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr);
123762a6ff1dSStefano Zampini   }
12388d00608fSStefano Zampini 
123927b6a85dSStefano Zampini   pcbddc->temp_solution_used = PETSC_FALSE;
12403972b0daSStefano Zampini   if (x) {
12413972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);
12423972b0daSStefano Zampini     used_vec = x;
12438d00608fSStefano Zampini   } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */
12443972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr);
12453972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
12463972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
124727b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
1248266e20e9SStefano Zampini     ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
1249266e20e9SStefano Zampini     save_rhs = PETSC_FALSE;
1250266e20e9SStefano Zampini     pcbddc->eliminate_dirdofs = PETSC_TRUE;
12513972b0daSStefano Zampini   }
12528efcfb23SStefano Zampini 
12538efcfb23SStefano Zampini   /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */
12543972b0daSStefano Zampini   if (ksp) {
1255a0cb1b98SStefano Zampini     /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */
12568efcfb23SStefano Zampini     ierr = KSPGetInitialGuessNonzero(ksp,&pcbddc->ksp_guess_nonzero);CHKERRQ(ierr);
12578efcfb23SStefano Zampini     if (!pcbddc->ksp_guess_nonzero) {
12583972b0daSStefano Zampini       ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
12593972b0daSStefano Zampini     }
12603972b0daSStefano Zampini   }
12613308cffdSStefano Zampini 
12628d00608fSStefano Zampini   pcbddc->rhs_change = PETSC_FALSE;
12633972b0daSStefano Zampini   /* Take into account zeroed rows -> change rhs and store solution removed */
126470c64980SStefano Zampini   if (rhs && pcbddc->eliminate_dirdofs) {
12653975b054SStefano Zampini     IS dirIS = NULL;
12663975b054SStefano Zampini 
1267a07ea27aSStefano Zampini     /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */
12683975b054SStefano Zampini     ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
12693975b054SStefano Zampini     if (dirIS) {
1270906d46d4SStefano Zampini       Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
1271785d1243SStefano Zampini       PetscInt          dirsize,i,*is_indices;
12722b095fd8SStefano Zampini       PetscScalar       *array_x;
12732b095fd8SStefano Zampini       const PetscScalar *array_diagonal;
1274785d1243SStefano Zampini 
12753972b0daSStefano Zampini       ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr);
12763972b0daSStefano Zampini       ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr);
1277e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1278e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1279e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1280e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
128182ba6b80SStefano Zampini       ierr = ISGetLocalSize(dirIS,&dirsize);CHKERRQ(ierr);
12823972b0daSStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
12832b095fd8SStefano Zampini       ierr = VecGetArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
12843972b0daSStefano Zampini       ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
12852fa5cd67SKarl Rupp       for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
12863972b0daSStefano Zampini       ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
12872b095fd8SStefano Zampini       ierr = VecRestoreArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
12883972b0daSStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
1289e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1290e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
12918d00608fSStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
12921b968477SStefano Zampini       ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
12938efcfb23SStefano Zampini     }
1294a07ea27aSStefano Zampini   }
1295b76ba322SStefano Zampini 
12968efcfb23SStefano Zampini   /* remove the computed solution or the initial guess from the rhs */
12978d00608fSStefano Zampini   if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero) ) {
129827b6a85dSStefano Zampini     /* save the original rhs */
129927b6a85dSStefano Zampini     if (save_rhs) {
130027b6a85dSStefano Zampini       ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
130127b6a85dSStefano Zampini       save_rhs = PETSC_FALSE;
13028d00608fSStefano Zampini     }
13038d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
13043972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
130527b6a85dSStefano Zampini     ierr = MatMultAdd(pc->mat,used_vec,pcbddc->original_rhs,rhs);CHKERRQ(ierr);
13063972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
13078efcfb23SStefano Zampini     ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr);
130827b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
13097acc28cbSStefano Zampini     if (ksp) {
13107acc28cbSStefano Zampini       ierr = KSPSetInitialGuessNonzero(ksp,PETSC_FALSE);CHKERRQ(ierr);
13117acc28cbSStefano Zampini     }
13123308cffdSStefano Zampini   }
13138efcfb23SStefano Zampini   ierr = VecDestroy(&used_vec);CHKERRQ(ierr);
1314b76ba322SStefano Zampini 
1315fc17d649SStefano Zampini   /* compute initial vector in benign space if needed
131627b6a85dSStefano Zampini      and remove non-benign solution from the rhs */
131727b6a85dSStefano Zampini   benign_correction_computed = PETSC_FALSE;
1318c69e9cc1SStefano Zampini   if (rhs && pcbddc->benign_compute_correction && (pcbddc->benign_have_null || pcbddc->benign_apply_coarse_only)) {
13191f4df5f7SStefano Zampini     /* compute u^*_h using ideas similar to those in Xuemin Tu's PhD thesis (see Section 4.8.1)
13201f4df5f7SStefano Zampini        Recursively apply BDDC in the multilevel case */
13210369aaf7SStefano Zampini     if (!pcbddc->benign_vec) {
13220369aaf7SStefano Zampini       ierr = VecDuplicate(rhs,&pcbddc->benign_vec);CHKERRQ(ierr);
13230369aaf7SStefano Zampini     }
1324c69e9cc1SStefano Zampini     /* keep applying coarse solver unless we no longer have benign subdomains */
1325c69e9cc1SStefano Zampini     pcbddc->benign_apply_coarse_only = pcbddc->benign_have_null ? PETSC_TRUE : PETSC_FALSE;
132627b6a85dSStefano Zampini     if (!pcbddc->benign_skip_correction) {
13271dd7afcfSStefano Zampini       ierr = PCApply_BDDC(pc,rhs,pcbddc->benign_vec);CHKERRQ(ierr);
13283bca92a6SStefano Zampini       benign_correction_computed = PETSC_TRUE;
13291f4df5f7SStefano Zampini       if (pcbddc->temp_solution_used) {
13301f4df5f7SStefano Zampini         ierr = VecAXPY(pcbddc->temp_solution,1.0,pcbddc->benign_vec);CHKERRQ(ierr);
13311f4df5f7SStefano Zampini       }
13321f4df5f7SStefano Zampini       ierr = VecScale(pcbddc->benign_vec,-1.0);CHKERRQ(ierr);
133327b6a85dSStefano Zampini       /* store the original rhs if not done earlier */
133427b6a85dSStefano Zampini       if (save_rhs) {
133527b6a85dSStefano Zampini         ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
133692e3dcfbSStefano Zampini       }
133727b6a85dSStefano Zampini       if (pcbddc->rhs_change) {
13380369aaf7SStefano Zampini         ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,rhs,rhs);CHKERRQ(ierr);
133927b6a85dSStefano Zampini       } else {
134027b6a85dSStefano Zampini         ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,pcbddc->original_rhs,rhs);CHKERRQ(ierr);
134127b6a85dSStefano Zampini       }
13420369aaf7SStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
134327b6a85dSStefano Zampini     }
134427b6a85dSStefano Zampini     pcbddc->benign_apply_coarse_only = PETSC_FALSE;
13450369aaf7SStefano Zampini   }
13462d4c4fecSStefano Zampini 
13472d4c4fecSStefano Zampini   /* dbg output */
1348a198735bSStefano Zampini   if (pcbddc->dbg_flag && benign_correction_computed) {
13491f4df5f7SStefano Zampini     Vec v;
1350c69e9cc1SStefano Zampini 
13511f4df5f7SStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&v);CHKERRQ(ierr);
1352c69e9cc1SStefano Zampini     if (pcbddc->ChangeOfBasisMatrix) {
13531f4df5f7SStefano Zampini       ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,v);CHKERRQ(ierr);
1354c69e9cc1SStefano Zampini     } else {
1355c69e9cc1SStefano Zampini       ierr = VecCopy(rhs,v);CHKERRQ(ierr);
1356c69e9cc1SStefano Zampini     }
13571f4df5f7SStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,v,PETSC_TRUE);CHKERRQ(ierr);
1358e0fe2d75SToby Isaac     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"LEVEL %D: is the correction benign?\n",pcbddc->current_level);CHKERRQ(ierr);
1359c69e9cc1SStefano Zampini     ierr = PetscScalarView(pcbddc->benign_n,pcbddc->benign_p0,pcbddc->dbg_viewer);CHKERRQ(ierr);
1360c69e9cc1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
13611f4df5f7SStefano Zampini     ierr = VecDestroy(&v);CHKERRQ(ierr);
13621f4df5f7SStefano Zampini   }
13630369aaf7SStefano Zampini 
13640369aaf7SStefano Zampini   /* set initial guess if using PCG */
13658ae0ca82SStefano Zampini   pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
13660369aaf7SStefano Zampini   if (x && pcbddc->use_exact_dirichlet_trick) {
13670369aaf7SStefano Zampini     ierr = VecSet(x,0.0);CHKERRQ(ierr);
13681dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
136927b6a85dSStefano Zampini       if (benign_correction_computed) { /* we have already saved the changed rhs */
13701dd7afcfSStefano Zampini         ierr = VecLockPop(pcis->vec1_global);CHKERRQ(ierr);
13711dd7afcfSStefano Zampini       } else {
13721dd7afcfSStefano Zampini         ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,pcis->vec1_global);CHKERRQ(ierr);
13731dd7afcfSStefano Zampini       }
13741dd7afcfSStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13751dd7afcfSStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13761dd7afcfSStefano Zampini     } else {
13770369aaf7SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13780369aaf7SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13791dd7afcfSStefano Zampini     }
13800369aaf7SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
13811dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
13821dd7afcfSStefano Zampini       ierr = VecSet(pcis->vec1_global,0.);CHKERRQ(ierr);
13831dd7afcfSStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13841dd7afcfSStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13851dd7afcfSStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x);CHKERRQ(ierr);
13861dd7afcfSStefano Zampini     } else {
13870369aaf7SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13880369aaf7SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13891dd7afcfSStefano Zampini     }
13900369aaf7SStefano Zampini     if (ksp) {
13910369aaf7SStefano Zampini       ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
13920369aaf7SStefano Zampini     }
13938ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_TRUE;
1394266e20e9SStefano Zampini   } else if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior && benign_correction_computed && pcbddc->use_exact_dirichlet_trick) {
1395266e20e9SStefano Zampini     ierr = VecLockPop(pcis->vec1_global);CHKERRQ(ierr);
13960369aaf7SStefano Zampini   }
1397534831adSStefano Zampini   PetscFunctionReturn(0);
1398534831adSStefano Zampini }
1399906d46d4SStefano Zampini 
1400534831adSStefano Zampini /*
1401534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
1402534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
1403534831adSStefano Zampini 
1404534831adSStefano Zampini    Input Parameter:
1405534831adSStefano Zampini +  pc - the preconditioner contex
1406534831adSStefano Zampini 
1407534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
1408534831adSStefano Zampini 
1409534831adSStefano Zampini    Notes:
1410534831adSStefano Zampini      The interface routine PCPostSolve() is not usually called directly by
1411534831adSStefano Zampini      the user, but instead is called by KSPSolve().
1412534831adSStefano Zampini */
1413534831adSStefano Zampini static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1414534831adSStefano Zampini {
1415534831adSStefano Zampini   PetscErrorCode ierr;
1416534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1417534831adSStefano Zampini 
1418534831adSStefano Zampini   PetscFunctionBegin;
14193972b0daSStefano Zampini   /* add solution removed in presolve */
14206bcfc461SStefano Zampini   if (x && pcbddc->rhs_change) {
142127b6a85dSStefano Zampini     if (pcbddc->temp_solution_used) {
14223425bc38SStefano Zampini       ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr);
1423af140850Sstefano_zampini     } else if (pcbddc->benign_compute_correction && pcbddc->benign_vec) {
142427b6a85dSStefano Zampini       ierr = VecAXPY(x,-1.0,pcbddc->benign_vec);CHKERRQ(ierr);
14253425bc38SStefano Zampini     }
1426af140850Sstefano_zampini     /* restore to original state (not for FETI-DP) */
1427af140850Sstefano_zampini     if (ksp) pcbddc->temp_solution_used = PETSC_FALSE;
142827b6a85dSStefano Zampini   }
142927b6a85dSStefano Zampini 
1430266e20e9SStefano Zampini   /* restore rhs to its original state (not needed for FETI-DP) */
14318d00608fSStefano Zampini   if (rhs && pcbddc->rhs_change) {
143227b6a85dSStefano Zampini     ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
14338d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_FALSE;
1434af140850Sstefano_zampini   }
14358efcfb23SStefano Zampini   /* restore ksp guess state */
14368efcfb23SStefano Zampini   if (ksp) {
14378efcfb23SStefano Zampini     ierr = KSPSetInitialGuessNonzero(ksp,pcbddc->ksp_guess_nonzero);CHKERRQ(ierr);
14388ae0ca82SStefano Zampini     /* reset flag for exact dirichlet trick */
14398ae0ca82SStefano Zampini     pcbddc->exact_dirichlet_trick_app = PETSC_FALSE;
1440af140850Sstefano_zampini   }
1441534831adSStefano Zampini   PetscFunctionReturn(0);
1442534831adSStefano Zampini }
1443af140850Sstefano_zampini 
14440c7d97c5SJed Brown /*
14450c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
14460c7d97c5SJed Brown                   by setting data structures and options.
14470c7d97c5SJed Brown 
14480c7d97c5SJed Brown    Input Parameter:
144953cdbc3dSStefano Zampini +  pc - the preconditioner context
14500c7d97c5SJed Brown 
14510c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
14520c7d97c5SJed Brown 
14530c7d97c5SJed Brown    Notes:
14540c7d97c5SJed Brown      The interface routine PCSetUp() is not usually called directly by
14550c7d97c5SJed Brown      the user, but instead is called by PCApply() if necessary.
14560c7d97c5SJed Brown */
145753cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
14580c7d97c5SJed Brown {
14590c7d97c5SJed Brown   PC_BDDC*        pcbddc = (PC_BDDC*)pc->data;
1460c703fcc7SStefano Zampini   PCBDDCSubSchurs sub_schurs;
14615e8657edSStefano Zampini   Mat_IS*         matis;
146208122e43SStefano Zampini   MatNullSpace    nearnullspace;
146335509ce9Sstefano_zampini   Mat             lA;
146435509ce9Sstefano_zampini   IS              lP,zerodiag = NULL;
146591e8d312SStefano Zampini   PetscInt        nrows,ncols;
146686bfa4cfSStefano Zampini   PetscMPIInt     size;
1467c703fcc7SStefano Zampini   PetscBool       computesubschurs;
14688de1fae6SStefano Zampini   PetscBool       computeconstraintsmatrix;
14695e8657edSStefano Zampini   PetscBool       new_nearnullspace_provided,ismatis;
1470c703fcc7SStefano Zampini   PetscErrorCode  ierr;
14710c7d97c5SJed Brown 
14720c7d97c5SJed Brown   PetscFunctionBegin;
14735e8657edSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATIS,&ismatis);CHKERRQ(ierr);
14746c4ed002SBarry Smith   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner requires matrix of type MATIS");
147591e8d312SStefano Zampini   ierr = MatGetSize(pc->pmat,&nrows,&ncols);CHKERRQ(ierr);
14766c4ed002SBarry Smith   if (nrows != ncols) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCBDDC preconditioner requires a square preconditioning matrix");
147786bfa4cfSStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&size);CHKERRQ(ierr);
147886bfa4cfSStefano Zampini 
14795e8657edSStefano Zampini   matis = (Mat_IS*)pc->pmat->data;
1480f4ddd8eeSStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */
14813b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
148271582508SStefano Zampini      Also, BDDC builds its own KSP for the Dirichlet problem */
1483a485753aSstefano_zampini   if (!pc->setupcalled || pc->flag == DIFFERENT_NONZERO_PATTERN) pcbddc->recompute_topography = PETSC_TRUE;
1484c83e1ba7SStefano Zampini   if (pcbddc->recompute_topography) {
1485c83e1ba7SStefano Zampini     pcbddc->graphanalyzed    = PETSC_FALSE;
1486c83e1ba7SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1487c83e1ba7SStefano Zampini   } else {
14888de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_FALSE;
1489c83e1ba7SStefano Zampini   }
1490b087196eSStefano Zampini 
1491b087196eSStefano Zampini   /* check parameters' compatibility */
1492b7ab4a40SStefano Zampini   if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE;
1493bd2a564bSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_threshold[0] != 0.0 || pcbddc->adaptive_threshold[1] != 0.0);
149486bfa4cfSStefano Zampini   pcbddc->use_deluxe_scaling   = (PetscBool)(pcbddc->use_deluxe_scaling && size > 1);
149586bfa4cfSStefano Zampini   pcbddc->adaptive_selection   = (PetscBool)(pcbddc->adaptive_selection && size > 1);
1496bf3a8328SStefano Zampini   pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined);
1497862806e4SStefano Zampini   if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE;
1498862806e4SStefano Zampini 
14995a95e1ceSStefano Zampini   computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling);
150016909a7fSStefano Zampini   if (pcbddc->switch_static) {
150116909a7fSStefano Zampini     PetscBool ismatis;
1502d9869140SStefano Zampini 
150316909a7fSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc->mat,MATIS,&ismatis);CHKERRQ(ierr);
150416909a7fSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"When the static switch is one, the iteration matrix should be of type MATIS");
150516909a7fSStefano Zampini   }
150616909a7fSStefano Zampini 
150771582508SStefano Zampini   /* activate all connected components if the netflux has been requested */
1508bb05f991SStefano Zampini   if (pcbddc->compute_nonetflux) {
1509bb05f991SStefano Zampini     pcbddc->use_vertices = PETSC_TRUE;
1510bb05f991SStefano Zampini     pcbddc->use_edges    = PETSC_TRUE;
1511bb05f991SStefano Zampini     pcbddc->use_faces    = PETSC_TRUE;
1512bb05f991SStefano Zampini   }
1513bb05f991SStefano Zampini 
1514f4ddd8eeSStefano Zampini   /* Get stdout for dbg */
151570cf5478SStefano Zampini   if (pcbddc->dbg_flag) {
151670cf5478SStefano Zampini     if (!pcbddc->dbg_viewer) {
151758a03d70SStefano Zampini       pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc));
1518f4ddd8eeSStefano Zampini     }
1519d9869140SStefano Zampini     ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
152058a03d70SStefano Zampini     ierr = PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
1521f4ddd8eeSStefano Zampini   }
1522f4ddd8eeSStefano Zampini 
1523c703fcc7SStefano Zampini   /* process topology information */
152471582508SStefano Zampini   if (pcbddc->recompute_topography) {
152571582508SStefano Zampini     ierr = PCBDDCComputeLocalTopologyInfo(pc);CHKERRQ(ierr);
1526c703fcc7SStefano Zampini     if (pcbddc->discretegradient) {
1527a13144ffSStefano Zampini       ierr = PCBDDCNedelecSupport(pc);CHKERRQ(ierr);
1528a13144ffSStefano Zampini     }
1529c703fcc7SStefano Zampini   }
1530a13144ffSStefano Zampini 
1531c703fcc7SStefano Zampini   /* change basis if requested by the user */
15325e8657edSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) {
15335e8657edSStefano Zampini     /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */
15345e8657edSStefano Zampini     pcbddc->use_change_of_basis = PETSC_FALSE;
15355e8657edSStefano Zampini     ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
15365e8657edSStefano Zampini   } else {
1537b96c3477SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
15385e8657edSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
15395e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
1540d16cbb6bSStefano Zampini   }
1541d16cbb6bSStefano Zampini 
15424f1b2e48SStefano Zampini   /*
1543c703fcc7SStefano Zampini      Compute change of basis on local pressures (aka zerodiag dofs) with the benign trick
15444f1b2e48SStefano Zampini      This should come earlier then PCISSetUp for extracting the correct subdomain matrices
15454f1b2e48SStefano Zampini   */
15461dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
1547d16cbb6bSStefano Zampini   if (pcbddc->benign_saddle_point) {
15489f47a83aSStefano Zampini     PC_IS* pcis = (PC_IS*)pc->data;
15499f47a83aSStefano Zampini 
155005b28244SStefano Zampini     if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE;
1551669cc0f4SStefano Zampini     /* detect local saddle point and change the basis in pcbddc->local_mat (TODO: reuse case) */
1552339f8db1SStefano Zampini     ierr = PCBDDCBenignDetectSaddlePoint(pc,&zerodiag);CHKERRQ(ierr);
1553a3df083aSStefano Zampini     /* pop B0 mat from local mat */
1554c263805aSStefano Zampini     ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
15551dd7afcfSStefano Zampini     /* give pcis a hint to not reuse submatrices during PCISCreate */
15561dd7afcfSStefano Zampini     if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) {
15571dd7afcfSStefano Zampini       if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) {
15581dd7afcfSStefano Zampini         pcis->reusesubmatrices = PETSC_FALSE;
15591dd7afcfSStefano Zampini       } else {
1560a3df083aSStefano Zampini         pcis->reusesubmatrices = PETSC_TRUE;
15611dd7afcfSStefano Zampini       }
1562a3df083aSStefano Zampini     } else {
15639f47a83aSStefano Zampini       pcis->reusesubmatrices = PETSC_FALSE;
1564674ae819SStefano Zampini     }
1565a3df083aSStefano Zampini   }
156627b6a85dSStefano Zampini 
15678037d520SStefano Zampini   /* propagate relevant information */
156806a4e24aSStefano Zampini   if (matis->A->symmetric_set) {
156906a4e24aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
157006a4e24aSStefano Zampini   }
157106a4e24aSStefano Zampini   if (matis->A->spd_set) {
157206a4e24aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SPD,matis->A->spd);CHKERRQ(ierr);
157306a4e24aSStefano Zampini   }
1574e496cd5dSStefano Zampini 
15755e8657edSStefano Zampini   /* Set up all the "iterative substructuring" common block without computing solvers */
15765e8657edSStefano Zampini   {
15775e8657edSStefano Zampini     Mat temp_mat;
15785e8657edSStefano Zampini 
15795e8657edSStefano Zampini     temp_mat = matis->A;
15805e8657edSStefano Zampini     matis->A = pcbddc->local_mat;
1581d9869140SStefano Zampini     ierr = PCISSetUp(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
15825e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
15835e8657edSStefano Zampini     matis->A = temp_mat;
15845e8657edSStefano Zampini   }
1585684f6988SStefano Zampini 
158681d14e9dSStefano Zampini   /* Analyze interface */
158764ac59b8SStefano Zampini   if (!pcbddc->graphanalyzed) {
1588674ae819SStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
15898de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1590345ecf6cSStefano Zampini     if (pcbddc->adaptive_selection && !pcbddc->use_deluxe_scaling && !pcbddc->mat_graph->twodim) {
15914247aa23Sstefano_zampini       SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot compute the adaptive primal space for a problem with 3D edges without deluxe scaling");
1592345ecf6cSStefano Zampini     }
1593a198735bSStefano Zampini     if (pcbddc->compute_nonetflux) {
1594669cc0f4SStefano Zampini       MatNullSpace nnfnnsp;
1595669cc0f4SStefano Zampini 
159621ef3d20SStefano Zampini       if (!pcbddc->divudotp) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Missing divudotp operator");
15978ae0ca82SStefano Zampini       ierr = PCBDDCComputeNoNetFlux(pc->pmat,pcbddc->divudotp,pcbddc->divudotp_trans,pcbddc->divudotp_vl2l,pcbddc->mat_graph,&nnfnnsp);CHKERRQ(ierr);
159871582508SStefano Zampini       /* TODO what if a nearnullspace is already attached? */
15998037d520SStefano Zampini       if (nnfnnsp) {
1600669cc0f4SStefano Zampini         ierr = MatSetNearNullSpace(pc->pmat,nnfnnsp);CHKERRQ(ierr);
1601669cc0f4SStefano Zampini         ierr = MatNullSpaceDestroy(&nnfnnsp);CHKERRQ(ierr);
1602669cc0f4SStefano Zampini       }
1603674ae819SStefano Zampini     }
16048037d520SStefano Zampini   }
1605fb8d54d4SStefano Zampini 
16065408967cSStefano Zampini   /* check existence of a divergence free extension, i.e.
16075408967cSStefano Zampini      b(v_I,p_0) = 0 for all v_I (raise error if not).
16085408967cSStefano Zampini      Also, check that PCBDDCBenignGetOrSetP0 works */
1609ff1f7e73Sstefano_zampini   if (pcbddc->benign_saddle_point && pcbddc->dbg_flag > 1) {
16105408967cSStefano Zampini     ierr = PCBDDCBenignCheck(pc,zerodiag);CHKERRQ(ierr);
161109f581a4SStefano Zampini   }
16124f1b2e48SStefano Zampini   ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
161306f24817SStefano Zampini 
1614b96c3477SStefano Zampini   /* Setup local dirichlet solver ksp_D and sub_schurs solvers */
1615c703fcc7SStefano Zampini   if (computesubschurs && pcbddc->recompute_topography) {
161608122e43SStefano Zampini     ierr = PCBDDCInitSubSchurs(pc);CHKERRQ(ierr);
1617b1b3d7a2SStefano Zampini   }
16189d54b7f4SStefano Zampini   /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/
16199d54b7f4SStefano Zampini   if (!pcbddc->use_deluxe_scaling) {
16209d54b7f4SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
16219d54b7f4SStefano Zampini   }
1622c703fcc7SStefano Zampini 
1623c703fcc7SStefano Zampini   /* finish setup solvers and do adaptive selection of constraints */
1624b334f244SStefano Zampini   sub_schurs = pcbddc->sub_schurs;
1625b334f244SStefano Zampini   if (sub_schurs && sub_schurs->schur_explicit) {
16262070dbb6SStefano Zampini     if (computesubschurs) {
162708122e43SStefano Zampini       ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
16282070dbb6SStefano Zampini     }
1629d5574798SStefano Zampini     ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
1630d5574798SStefano Zampini   } else {
1631d5574798SStefano Zampini     ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
16322070dbb6SStefano Zampini     if (computesubschurs) {
1633d5574798SStefano Zampini       ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
1634d5574798SStefano Zampini     }
16352070dbb6SStefano Zampini   }
163608122e43SStefano Zampini   if (pcbddc->adaptive_selection) {
163708122e43SStefano Zampini     ierr = PCBDDCAdaptiveSelection(pc);CHKERRQ(ierr);
16388de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1639b7eb3628SStefano Zampini   }
1640684f6988SStefano Zampini 
1641f4ddd8eeSStefano Zampini   /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */
1642fb8d54d4SStefano Zampini   new_nearnullspace_provided = PETSC_FALSE;
1643f4ddd8eeSStefano Zampini   ierr = MatGetNearNullSpace(pc->pmat,&nearnullspace);CHKERRQ(ierr);
1644f4ddd8eeSStefano Zampini   if (pcbddc->onearnullspace) { /* already used nearnullspace */
1645f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* near null space attached to mat has been destroyed */
1646f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1647f4ddd8eeSStefano Zampini     } else {
1648f4ddd8eeSStefano Zampini       /* determine if the two nullspaces are different (should be lightweight) */
1649f4ddd8eeSStefano Zampini       if (nearnullspace != pcbddc->onearnullspace) {
1650f4ddd8eeSStefano Zampini         new_nearnullspace_provided = PETSC_TRUE;
1651165b64e2SStefano Zampini       } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */
1652f4ddd8eeSStefano Zampini         PetscInt         i;
1653165b64e2SStefano Zampini         const Vec        *nearnullvecs;
1654165b64e2SStefano Zampini         PetscObjectState state;
1655165b64e2SStefano Zampini         PetscInt         nnsp_size;
1656165b64e2SStefano Zampini         ierr = MatNullSpaceGetVecs(nearnullspace,NULL,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
1657f4ddd8eeSStefano Zampini         for (i=0;i<nnsp_size;i++) {
1658f4ddd8eeSStefano Zampini           ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&state);CHKERRQ(ierr);
1659165b64e2SStefano Zampini           if (pcbddc->onearnullvecs_state[i] != state) {
1660f4ddd8eeSStefano Zampini             new_nearnullspace_provided = PETSC_TRUE;
1661f4ddd8eeSStefano Zampini             break;
1662f4ddd8eeSStefano Zampini           }
1663f4ddd8eeSStefano Zampini         }
1664f4ddd8eeSStefano Zampini       }
1665f4ddd8eeSStefano Zampini     }
1666f4ddd8eeSStefano Zampini   } else {
1667f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* both nearnullspaces are null */
1668f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_FALSE;
1669f4ddd8eeSStefano Zampini     } else { /* nearnullspace attached later */
1670f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1671f4ddd8eeSStefano Zampini     }
1672f4ddd8eeSStefano Zampini   }
1673f4ddd8eeSStefano Zampini 
1674f4ddd8eeSStefano Zampini   /* Setup constraints and related work vectors */
1675727cdba6SStefano Zampini   /* reset primal space flags */
1676f4ddd8eeSStefano Zampini   pcbddc->new_primal_space = PETSC_FALSE;
1677727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_FALSE;
16788de1fae6SStefano Zampini   if (computeconstraintsmatrix || new_nearnullspace_provided) {
1679727cdba6SStefano Zampini     /* It also sets the primal space flags */
1680674ae819SStefano Zampini     ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr);
16819543d0ffSStefano Zampini   }
1682e7b262bdSStefano Zampini   /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */
1683f4ddd8eeSStefano Zampini   ierr = PCBDDCSetUpLocalWorkVectors(pc);CHKERRQ(ierr);
16845e8657edSStefano Zampini 
16855e8657edSStefano Zampini   if (pcbddc->use_change_of_basis) {
16865e8657edSStefano Zampini     PC_IS *pcis = (PC_IS*)(pc->data);
16875e8657edSStefano Zampini 
16885e8657edSStefano Zampini     ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
16894f1b2e48SStefano Zampini     if (pcbddc->benign_change) {
16901dd7afcfSStefano Zampini       ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
1691c263805aSStefano Zampini       /* pop B0 from pcbddc->local_mat */
1692c263805aSStefano Zampini       ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
1693c263805aSStefano Zampini     }
16945e8657edSStefano Zampini     /* get submatrices */
16955e8657edSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
16965e8657edSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
16975e8657edSStefano Zampini     ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);
16987dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB);CHKERRQ(ierr);
16997dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr);
17007dae84e0SHong Zhang     ierr = MatCreateSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr);
17013975b054SStefano Zampini     /* set flag in pcis to not reuse submatrices during PCISCreate */
17023975b054SStefano Zampini     pcis->reusesubmatrices = PETSC_FALSE;
17039c6a02ceSStefano Zampini   } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) {
1704b96c3477SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
17055e8657edSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
17065e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
17075e8657edSStefano Zampini   }
170835509ce9Sstefano_zampini 
170935509ce9Sstefano_zampini   /* interface pressure block row for B_C */
171035509ce9Sstefano_zampini   ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lP" ,(PetscObject*)&lP);CHKERRQ(ierr);
171135509ce9Sstefano_zampini   ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_lA" ,(PetscObject*)&lA);CHKERRQ(ierr);
171235509ce9Sstefano_zampini   if (lA && lP) {
171335509ce9Sstefano_zampini     PC_IS*    pcis = (PC_IS*)pc->data;
171435509ce9Sstefano_zampini     Mat       B_BI,B_BB,Bt_BI,Bt_BB;
171535509ce9Sstefano_zampini     PetscBool issym;
171635509ce9Sstefano_zampini     ierr = MatIsSymmetric(lA,PETSC_SMALL,&issym);CHKERRQ(ierr);
17176cc1294bSstefano_zampini     if (issym) {
17187dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI);CHKERRQ(ierr);
17197dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB);CHKERRQ(ierr);
172035509ce9Sstefano_zampini       ierr = MatCreateTranspose(B_BI,&Bt_BI);CHKERRQ(ierr);
172135509ce9Sstefano_zampini       ierr = MatCreateTranspose(B_BB,&Bt_BB);CHKERRQ(ierr);
172235509ce9Sstefano_zampini     } else {
17237dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_I_local,MAT_INITIAL_MATRIX,&B_BI);CHKERRQ(ierr);
17247dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,lP,pcis->is_B_local,MAT_INITIAL_MATRIX,&B_BB);CHKERRQ(ierr);
17257dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,pcis->is_I_local,lP,MAT_INITIAL_MATRIX,&Bt_BI);CHKERRQ(ierr);
17267dae84e0SHong Zhang       ierr = MatCreateSubMatrix(lA,pcis->is_B_local,lP,MAT_INITIAL_MATRIX,&Bt_BB);CHKERRQ(ierr);
172735509ce9Sstefano_zampini     }
172835509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BI",(PetscObject)B_BI);CHKERRQ(ierr);
172935509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_B_BB",(PetscObject)B_BB);CHKERRQ(ierr);
173035509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BI",(PetscObject)Bt_BI);CHKERRQ(ierr);
173135509ce9Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)pc,"__KSPFETIDP_Bt_BB",(PetscObject)Bt_BB);CHKERRQ(ierr);
173235509ce9Sstefano_zampini     ierr = MatDestroy(&B_BI);CHKERRQ(ierr);
173335509ce9Sstefano_zampini     ierr = MatDestroy(&B_BB);CHKERRQ(ierr);
173435509ce9Sstefano_zampini     ierr = MatDestroy(&Bt_BI);CHKERRQ(ierr);
173535509ce9Sstefano_zampini     ierr = MatDestroy(&Bt_BB);CHKERRQ(ierr);
173635509ce9Sstefano_zampini   }
173735509ce9Sstefano_zampini 
1738b96c3477SStefano Zampini   /* SetUp coarse and local Neumann solvers */
173999cc7994SStefano Zampini   ierr = PCBDDCSetUpSolvers(pc);CHKERRQ(ierr);
1740b96c3477SStefano Zampini   /* SetUp Scaling operator */
17419d54b7f4SStefano Zampini   if (pcbddc->use_deluxe_scaling) {
1742674ae819SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
17430c7d97c5SJed Brown   }
1744c703fcc7SStefano Zampini 
17451dd7afcfSStefano Zampini   /* mark topography as done */
174656282151SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
17470369aaf7SStefano Zampini 
17481dd7afcfSStefano Zampini   /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */
17491dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_FALSE);CHKERRQ(ierr);
17501dd7afcfSStefano Zampini 
175158a03d70SStefano Zampini   if (pcbddc->dbg_flag) {
175258a03d70SStefano Zampini     ierr = PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
1753d9869140SStefano Zampini     ierr = PetscViewerASCIIPopSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
17542b510759SStefano Zampini   }
17550c7d97c5SJed Brown   PetscFunctionReturn(0);
17560c7d97c5SJed Brown }
17570c7d97c5SJed Brown 
17580c7d97c5SJed Brown /*
175950efa1b5SStefano Zampini    PCApply_BDDC - Applies the BDDC operator to a vector.
17600c7d97c5SJed Brown 
17610c7d97c5SJed Brown    Input Parameters:
17620f202f7eSStefano Zampini +  pc - the preconditioner context
17630f202f7eSStefano Zampini -  r - input vector (global)
17640c7d97c5SJed Brown 
17650c7d97c5SJed Brown    Output Parameter:
17660c7d97c5SJed Brown .  z - output vector (global)
17670c7d97c5SJed Brown 
17680c7d97c5SJed Brown    Application Interface Routine: PCApply()
17690c7d97c5SJed Brown  */
177053cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
17710c7d97c5SJed Brown {
17720c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
17730c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1774b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
17750c7d97c5SJed Brown   PetscErrorCode    ierr;
17763b03a366Sstefano_zampini   const PetscScalar one = 1.0;
17773b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
17782617d88aSStefano Zampini   const PetscScalar zero = 0.0;
17790c7d97c5SJed Brown 
17800c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
17810c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
1782b097fa66SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */
17830c7d97c5SJed Brown 
17840c7d97c5SJed Brown   PetscFunctionBegin;
1785f3d41395Sstefano_zampini   ierr = PetscCitationsRegister(citation,&cited);CHKERRQ(ierr);
17861dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
17871dd7afcfSStefano Zampini     Vec swap;
178827b6a85dSStefano Zampini 
178927b6a85dSStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
17901dd7afcfSStefano Zampini     swap = pcbddc->work_change;
17911dd7afcfSStefano Zampini     pcbddc->work_change = r;
17921dd7afcfSStefano Zampini     r = swap;
17931dd7afcfSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
17949cc2a9b1Sstefano_zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) {
17951dd7afcfSStefano Zampini       ierr = VecCopy(r,pcis->vec1_global);CHKERRQ(ierr);
17961dd7afcfSStefano Zampini       ierr = VecLockPush(pcis->vec1_global);CHKERRQ(ierr);
17971dd7afcfSStefano Zampini     }
17981dd7afcfSStefano Zampini   }
179927b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
1800015636ebSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
1801efc2fbd9SStefano Zampini   }
18028ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1803b097fa66SStefano Zampini     ierr = VecCopy(r,z);CHKERRQ(ierr);
18040c7d97c5SJed Brown     /* First Dirichlet solve */
18050c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18060c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18070c7d97c5SJed Brown     /*
18080c7d97c5SJed Brown       Assembling right hand side for BDDC operator
1809b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
1810674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
18110c7d97c5SJed Brown     */
1812b097fa66SStefano Zampini     if (n_D) {
1813b097fa66SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
18140c7d97c5SJed Brown       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
181516909a7fSStefano Zampini       if (pcbddc->switch_static) {
181616909a7fSStefano Zampini         Mat_IS *matis = (Mat_IS*)(pc->mat->data);
181716909a7fSStefano Zampini 
181816909a7fSStefano Zampini         ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
181916909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
182016909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
182116909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
182216909a7fSStefano Zampini           ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
182316909a7fSStefano Zampini         } else {
182416909a7fSStefano Zampini           ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
182516909a7fSStefano Zampini           ierr = MatMult(matis->A,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
182616909a7fSStefano Zampini           ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
182716909a7fSStefano Zampini         }
182816909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
182916909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
183016909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
183116909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
183216909a7fSStefano Zampini       } else {
1833b097fa66SStefano Zampini         ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
183416909a7fSStefano Zampini       }
1835b097fa66SStefano Zampini     } else {
1836b097fa66SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1837b097fa66SStefano Zampini     }
18380c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
18390c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1840674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
1841b76ba322SStefano Zampini   } else {
18424fee134fSStefano Zampini     if (!pcbddc->benign_apply_coarse_only) {
1843674ae819SStefano Zampini       ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
1844b76ba322SStefano Zampini     }
18454fee134fSStefano Zampini   }
1846b76ba322SStefano Zampini 
18472617d88aSStefano Zampini   /* Apply interface preconditioner
18482617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
1849dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
18502617d88aSStefano Zampini 
1851674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
1852674ae819SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
18530c7d97c5SJed Brown 
18543b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
18550c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18560c7d97c5SJed Brown   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1857b097fa66SStefano Zampini   if (n_B) {
185816909a7fSStefano Zampini     if (pcbddc->switch_static) {
185916909a7fSStefano Zampini       Mat_IS *matis = (Mat_IS*)(pc->mat->data);
186016909a7fSStefano Zampini 
186116909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
186216909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
186316909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
186416909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
186516909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
186616909a7fSStefano Zampini         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
186716909a7fSStefano Zampini       } else {
186816909a7fSStefano Zampini         ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
186916909a7fSStefano Zampini         ierr = MatMult(matis->A,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
187016909a7fSStefano Zampini         ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
187116909a7fSStefano Zampini       }
187216909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
187316909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
187416909a7fSStefano Zampini     } else {
18750c7d97c5SJed Brown       ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
187616909a7fSStefano Zampini     }
187716909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
187816909a7fSStefano Zampini     Mat_IS *matis = (Mat_IS*)(pc->mat->data);
187916909a7fSStefano Zampini 
188016909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
188116909a7fSStefano Zampini       ierr = MatMult(matis->A,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
188216909a7fSStefano Zampini     } else {
188316909a7fSStefano Zampini       ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N);CHKERRQ(ierr);
188416909a7fSStefano Zampini       ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
188516909a7fSStefano Zampini       ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D);CHKERRQ(ierr);
188616909a7fSStefano Zampini     }
1887b097fa66SStefano Zampini   }
1888df187020SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
1889efc2fbd9SStefano Zampini 
18908ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1891b097fa66SStefano Zampini     if (pcbddc->switch_static) {
1892b097fa66SStefano Zampini       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
1893b097fa66SStefano Zampini     } else {
1894b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
1895b097fa66SStefano Zampini     }
18960c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
18970c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1898b097fa66SStefano Zampini   } else {
1899b097fa66SStefano Zampini     if (pcbddc->switch_static) {
1900b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
1901b097fa66SStefano Zampini     } else {
1902b097fa66SStefano Zampini       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
1903b097fa66SStefano Zampini     }
1904b097fa66SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1905b097fa66SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1906b097fa66SStefano Zampini   }
190727b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
19081dd7afcfSStefano Zampini     if (pcbddc->benign_apply_coarse_only) {
19091dd7afcfSStefano Zampini       ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
19101dd7afcfSStefano Zampini     }
1911015636ebSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
1912efc2fbd9SStefano Zampini   }
19131f4df5f7SStefano Zampini 
19141dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1915f913dca9SStefano Zampini     pcbddc->work_change = r;
19161dd7afcfSStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
19171dd7afcfSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
19181dd7afcfSStefano Zampini   }
19190c7d97c5SJed Brown   PetscFunctionReturn(0);
19200c7d97c5SJed Brown }
192150efa1b5SStefano Zampini 
192250efa1b5SStefano Zampini /*
192350efa1b5SStefano Zampini    PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector.
192450efa1b5SStefano Zampini 
192550efa1b5SStefano Zampini    Input Parameters:
19260f202f7eSStefano Zampini +  pc - the preconditioner context
19270f202f7eSStefano Zampini -  r - input vector (global)
192850efa1b5SStefano Zampini 
192950efa1b5SStefano Zampini    Output Parameter:
193050efa1b5SStefano Zampini .  z - output vector (global)
193150efa1b5SStefano Zampini 
193250efa1b5SStefano Zampini    Application Interface Routine: PCApplyTranspose()
193350efa1b5SStefano Zampini  */
193450efa1b5SStefano Zampini PetscErrorCode PCApplyTranspose_BDDC(PC pc,Vec r,Vec z)
193550efa1b5SStefano Zampini {
193650efa1b5SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
193750efa1b5SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1938b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
193950efa1b5SStefano Zampini   PetscErrorCode    ierr;
194050efa1b5SStefano Zampini   const PetscScalar one = 1.0;
194150efa1b5SStefano Zampini   const PetscScalar m_one = -1.0;
194250efa1b5SStefano Zampini   const PetscScalar zero = 0.0;
194350efa1b5SStefano Zampini 
194450efa1b5SStefano Zampini   PetscFunctionBegin;
1945f3d41395Sstefano_zampini   ierr = PetscCitationsRegister(citation,&cited);CHKERRQ(ierr);
19461dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
19471dd7afcfSStefano Zampini     Vec swap;
194827b6a85dSStefano Zampini 
194927b6a85dSStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
19501dd7afcfSStefano Zampini     swap = pcbddc->work_change;
19511dd7afcfSStefano Zampini     pcbddc->work_change = r;
19521dd7afcfSStefano Zampini     r = swap;
195327b6a85dSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
19548ae0ca82SStefano Zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->exact_dirichlet_trick_app && pcbddc->change_interior) {
195527b6a85dSStefano Zampini       ierr = VecCopy(r,pcis->vec1_global);CHKERRQ(ierr);
195627b6a85dSStefano Zampini       ierr = VecLockPush(pcis->vec1_global);CHKERRQ(ierr);
19571dd7afcfSStefano Zampini     }
195827b6a85dSStefano Zampini   }
195927b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
1960537c1cdfSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
1961537c1cdfSStefano Zampini   }
19628ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
1963b097fa66SStefano Zampini     ierr = VecCopy(r,z);CHKERRQ(ierr);
196450efa1b5SStefano Zampini     /* First Dirichlet solve */
196550efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
196650efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
196750efa1b5SStefano Zampini     /*
196850efa1b5SStefano Zampini       Assembling right hand side for BDDC operator
1969b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
197050efa1b5SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
197150efa1b5SStefano Zampini     */
1972b097fa66SStefano Zampini     if (n_D) {
1973b097fa66SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
197450efa1b5SStefano Zampini       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
197516909a7fSStefano Zampini       if (pcbddc->switch_static) {
197616909a7fSStefano Zampini         Mat_IS *matis = (Mat_IS*)(pc->mat->data);
197716909a7fSStefano Zampini 
197816909a7fSStefano Zampini         ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
197916909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
198016909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
198116909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
198216909a7fSStefano Zampini           ierr = MatMultTranspose(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
198316909a7fSStefano Zampini         } else {
198416909a7fSStefano Zampini           ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
198516909a7fSStefano Zampini           ierr = MatMultTranspose(matis->A,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
198616909a7fSStefano Zampini           ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
198716909a7fSStefano Zampini         }
198816909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
198916909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
199016909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
199116909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
199216909a7fSStefano Zampini       } else {
1993b097fa66SStefano Zampini         ierr = MatMultTranspose(pcis->A_IB,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
199416909a7fSStefano Zampini       }
1995b097fa66SStefano Zampini     } else {
1996b097fa66SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1997b097fa66SStefano Zampini     }
199850efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
199950efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
200050efa1b5SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
200150efa1b5SStefano Zampini   } else {
200250efa1b5SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
200350efa1b5SStefano Zampini   }
200450efa1b5SStefano Zampini 
200550efa1b5SStefano Zampini   /* Apply interface preconditioner
200650efa1b5SStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
2007dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_TRUE);CHKERRQ(ierr);
200850efa1b5SStefano Zampini 
200950efa1b5SStefano Zampini   /* Apply transpose of partition of unity operator */
201050efa1b5SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
201150efa1b5SStefano Zampini 
201250efa1b5SStefano Zampini   /* Second Dirichlet solve and assembling of output */
201350efa1b5SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
201450efa1b5SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2015b097fa66SStefano Zampini   if (n_B) {
201616909a7fSStefano Zampini     if (pcbddc->switch_static) {
201716909a7fSStefano Zampini       Mat_IS *matis = (Mat_IS*)(pc->mat->data);
201816909a7fSStefano Zampini 
201916909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
202016909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
202116909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
202216909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
202316909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
202416909a7fSStefano Zampini         ierr = MatMultTranspose(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
202516909a7fSStefano Zampini       } else {
202616909a7fSStefano Zampini         ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
202716909a7fSStefano Zampini         ierr = MatMultTranspose(matis->A,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
202816909a7fSStefano Zampini         ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
202916909a7fSStefano Zampini       }
203016909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
203116909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
203216909a7fSStefano Zampini     } else {
203350efa1b5SStefano Zampini       ierr = MatMultTranspose(pcis->A_BI,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
203416909a7fSStefano Zampini     }
203516909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
203616909a7fSStefano Zampini     Mat_IS *matis = (Mat_IS*)(pc->mat->data);
203716909a7fSStefano Zampini 
203816909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
203916909a7fSStefano Zampini       ierr = MatMultTranspose(matis->A,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
204016909a7fSStefano Zampini     } else {
204116909a7fSStefano Zampini       ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N);CHKERRQ(ierr);
204216909a7fSStefano Zampini       ierr = MatMultTranspose(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
204316909a7fSStefano Zampini       ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D);CHKERRQ(ierr);
204416909a7fSStefano Zampini     }
2045b097fa66SStefano Zampini   }
2046b0147a47SStefano Zampini   ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
20478ae0ca82SStefano Zampini   if (!pcbddc->exact_dirichlet_trick_app && !pcbddc->benign_apply_coarse_only) {
2048b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2049b097fa66SStefano Zampini       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
2050b097fa66SStefano Zampini     } else {
2051b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
2052b097fa66SStefano Zampini     }
205350efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
205450efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2055b097fa66SStefano Zampini   } else {
2056b097fa66SStefano Zampini     if (pcbddc->switch_static) {
2057b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
2058b097fa66SStefano Zampini     } else {
2059b097fa66SStefano Zampini       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
2060b097fa66SStefano Zampini     }
2061b097fa66SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2062b097fa66SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2063b097fa66SStefano Zampini   }
206427b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
2065537c1cdfSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
2066537c1cdfSStefano Zampini   }
20671dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2068f913dca9SStefano Zampini     pcbddc->work_change = r;
20691dd7afcfSStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
20701dd7afcfSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
20711dd7afcfSStefano Zampini   }
207250efa1b5SStefano Zampini   PetscFunctionReturn(0);
207350efa1b5SStefano Zampini }
2074674ae819SStefano Zampini 
20759326c5c6Sstefano_zampini PetscErrorCode PCReset_BDDC(PC pc)
2076da1bb401SStefano Zampini {
2077da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
20789326c5c6Sstefano_zampini   PC_IS          *pcis = (PC_IS*)pc->data;
20799326c5c6Sstefano_zampini   KSP            kspD,kspR,kspC;
2080da1bb401SStefano Zampini   PetscErrorCode ierr;
2081da1bb401SStefano Zampini 
2082da1bb401SStefano Zampini   PetscFunctionBegin;
2083674ae819SStefano Zampini   /* free BDDC custom data  */
2084674ae819SStefano Zampini   ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr);
2085674ae819SStefano Zampini   /* destroy objects related to topography */
2086674ae819SStefano Zampini   ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
208734a97f8cSStefano Zampini   /* destroy objects for scaling operator */
2088674ae819SStefano Zampini   ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
2089674ae819SStefano Zampini   /* free solvers stuff */
2090674ae819SStefano Zampini   ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
209162a6ff1dSStefano Zampini   /* free global vectors needed in presolve */
209262a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr);
209362a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr);
20941dd7afcfSStefano Zampini   /* free data created by PCIS */
20951dd7afcfSStefano Zampini   ierr = PCISDestroy(pc);CHKERRQ(ierr);
20969326c5c6Sstefano_zampini 
20979326c5c6Sstefano_zampini   /* restore defaults */
20989326c5c6Sstefano_zampini   kspD = pcbddc->ksp_D;
20999326c5c6Sstefano_zampini   kspR = pcbddc->ksp_R;
21009326c5c6Sstefano_zampini   kspC = pcbddc->coarse_ksp;
21019326c5c6Sstefano_zampini   ierr = PetscMemzero(pc->data,sizeof(*pcbddc));CHKERRQ(ierr);
21029326c5c6Sstefano_zampini   pcis->n_neigh                     = -1;
21039326c5c6Sstefano_zampini   pcis->scaling_factor              = 1.0;
21049326c5c6Sstefano_zampini   pcis->reusesubmatrices            = PETSC_TRUE;
21059326c5c6Sstefano_zampini   pcbddc->use_local_adj             = PETSC_TRUE;
21069326c5c6Sstefano_zampini   pcbddc->use_vertices              = PETSC_TRUE;
21079326c5c6Sstefano_zampini   pcbddc->use_edges                 = PETSC_TRUE;
21089326c5c6Sstefano_zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
21099326c5c6Sstefano_zampini   pcbddc->vertex_size               = 1;
21109326c5c6Sstefano_zampini   pcbddc->recompute_topography      = PETSC_TRUE;
21119326c5c6Sstefano_zampini   pcbddc->coarse_size               = -1;
21129326c5c6Sstefano_zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
21139326c5c6Sstefano_zampini   pcbddc->coarsening_ratio          = 8;
21149326c5c6Sstefano_zampini   pcbddc->coarse_eqs_per_proc       = 1;
21159326c5c6Sstefano_zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
21169326c5c6Sstefano_zampini   pcbddc->nedfield                  = -1;
21179326c5c6Sstefano_zampini   pcbddc->nedglobal                 = PETSC_TRUE;
21189326c5c6Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
21199326c5c6Sstefano_zampini   pcbddc->sub_schurs_layers         = -1;
21209326c5c6Sstefano_zampini   pcbddc->ksp_D                     = kspD;
21219326c5c6Sstefano_zampini   pcbddc->ksp_R                     = kspR;
21229326c5c6Sstefano_zampini   pcbddc->coarse_ksp                = kspC;
21239326c5c6Sstefano_zampini   PetscFunctionReturn(0);
21249326c5c6Sstefano_zampini }
21259326c5c6Sstefano_zampini 
21269326c5c6Sstefano_zampini PetscErrorCode PCDestroy_BDDC(PC pc)
21279326c5c6Sstefano_zampini {
21289326c5c6Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
21299326c5c6Sstefano_zampini   PetscErrorCode ierr;
21309326c5c6Sstefano_zampini 
21319326c5c6Sstefano_zampini   PetscFunctionBegin;
21329326c5c6Sstefano_zampini   ierr = PCReset_BDDC(pc);CHKERRQ(ierr);
21339326c5c6Sstefano_zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
21349326c5c6Sstefano_zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
21359326c5c6Sstefano_zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
2136a13144ffSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",NULL);CHKERRQ(ierr);
2137a198735bSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",NULL);CHKERRQ(ierr);
2138906d46d4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",NULL);CHKERRQ(ierr);
2139674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr);
214030368db7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",NULL);CHKERRQ(ierr);
2141bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr);
21422b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL);CHKERRQ(ierr);
2143b8ffe317SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL);CHKERRQ(ierr);
21442b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL);CHKERRQ(ierr);
2145bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
214682ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
2147bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
214882ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
2149bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
215082ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
2151bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
2152785d1243SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
2153bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr);
215463602bcaSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",NULL);CHKERRQ(ierr);
2155bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr);
2156bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr);
2157bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr);
2158bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr);
2159a06fd7f2SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",NULL);CHKERRQ(ierr);
2160ab8c8b98SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",NULL);CHKERRQ(ierr);
2161674ae819SStefano Zampini   ierr = PetscFree(pc->data);CHKERRQ(ierr);
2162da1bb401SStefano Zampini   PetscFunctionReturn(0);
2163da1bb401SStefano Zampini }
21641e6b0712SBarry Smith 
2165ab8c8b98SStefano Zampini static PetscErrorCode PCSetCoordinates_BDDC(PC pc, PetscInt dim, PetscInt nloc, PetscReal *coords)
2166ab8c8b98SStefano Zampini {
2167ab8c8b98SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
2168ab8c8b98SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
2169ab8c8b98SStefano Zampini   PetscErrorCode ierr;
2170ab8c8b98SStefano Zampini 
2171ab8c8b98SStefano Zampini   PetscFunctionBegin;
2172ab8c8b98SStefano Zampini   ierr = PetscFree(mat_graph->coords);CHKERRQ(ierr);
2173ab8c8b98SStefano Zampini   ierr = PetscMalloc1(nloc*dim,&mat_graph->coords);CHKERRQ(ierr);
2174ab8c8b98SStefano Zampini   ierr = PetscMemcpy(mat_graph->coords,coords,nloc*dim*sizeof(PetscReal));CHKERRQ(ierr);
2175ab8c8b98SStefano Zampini   mat_graph->cnloc = nloc;
2176ab8c8b98SStefano Zampini   mat_graph->cdim  = dim;
2177ab8c8b98SStefano Zampini   mat_graph->cloc  = PETSC_FALSE;
2178ab8c8b98SStefano Zampini   PetscFunctionReturn(0);
2179ab8c8b98SStefano Zampini }
2180ab8c8b98SStefano Zampini 
2181a06fd7f2SStefano Zampini static PetscErrorCode PCPreSolveChangeRHS_BDDC(PC pc, PetscBool* change)
2182a06fd7f2SStefano Zampini {
2183a06fd7f2SStefano Zampini   PetscFunctionBegin;
2184a06fd7f2SStefano Zampini   *change = PETSC_TRUE;
2185a06fd7f2SStefano Zampini   PetscFunctionReturn(0);
2186a06fd7f2SStefano Zampini }
2187a06fd7f2SStefano Zampini 
21883425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
21893425bc38SStefano Zampini {
2190674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
2191266e20e9SStefano Zampini   Vec            work;
21923425bc38SStefano Zampini   PC_IS*         pcis;
21933425bc38SStefano Zampini   PC_BDDC*       pcbddc;
21943425bc38SStefano Zampini   PetscErrorCode ierr;
21950c7d97c5SJed Brown 
21963425bc38SStefano Zampini   PetscFunctionBegin;
21973425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
21983425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
21993425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
22003425bc38SStefano Zampini 
2201229984c5Sstefano_zampini   ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr);
2202229984c5Sstefano_zampini   /* copy rhs since we may change it during PCPreSolve_BDDC */
2203229984c5Sstefano_zampini   if (!pcbddc->original_rhs) {
2204229984c5Sstefano_zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
2205229984c5Sstefano_zampini   }
22066cc1294bSstefano_zampini   if (mat_ctx->rhs_flip) {
22076cc1294bSstefano_zampini     ierr = VecPointwiseMult(pcbddc->original_rhs,standard_rhs,mat_ctx->rhs_flip);CHKERRQ(ierr);
22086cc1294bSstefano_zampini   } else {
2209229984c5Sstefano_zampini     ierr = VecCopy(standard_rhs,pcbddc->original_rhs);CHKERRQ(ierr);
22106cc1294bSstefano_zampini   }
2211af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
2212229984c5Sstefano_zampini     /* interface pressure rhs */
2213022d8d2bSstefano_zampini     ierr = VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2214022d8d2bSstefano_zampini     ierr = VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_rhs,pcbddc->original_rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2215229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2216229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->g2g_p,standard_rhs,fetidp_flux_rhs,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
22176cc1294bSstefano_zampini     if (!mat_ctx->rhs_flip) {
2218229984c5Sstefano_zampini       ierr = VecScale(fetidp_flux_rhs,-1.);CHKERRQ(ierr);
2219229984c5Sstefano_zampini     }
22206cc1294bSstefano_zampini   }
2221c08af4c6SStefano Zampini   /*
2222c08af4c6SStefano Zampini      change of basis for physical rhs if needed
2223c08af4c6SStefano Zampini      It also changes the rhs in case of dirichlet boundaries
2224c08af4c6SStefano Zampini   */
22253738a8e6SStefano Zampini   ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,pcbddc->original_rhs,NULL);CHKERRQ(ierr);
2226fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
22273738a8e6SStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,pcbddc->original_rhs,pcbddc->work_change);CHKERRQ(ierr);
22283738a8e6SStefano Zampini     work = pcbddc->work_change;
2229fc17d649SStefano Zampini    } else {
22303738a8e6SStefano Zampini     work = pcbddc->original_rhs;
2231fc17d649SStefano Zampini   }
22323425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
2233266e20e9SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2234266e20e9SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,work,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2235fb223d50SStefano Zampini   /* scale rhs since it should be unassembled */
2236fb223d50SStefano Zampini   /* TODO use counter scaling? (also below) */
2237266e20e9SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2238266e20e9SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2239674ae819SStefano Zampini   /* Apply partition of unity */
22403425bc38SStefano Zampini   ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
2241266e20e9SStefano Zampini   /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
22428eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
22433425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
22443425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
22453425bc38SStefano Zampini     ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr);
22463425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr);
2247266e20e9SStefano Zampini     ierr = VecSet(work,0.0);CHKERRQ(ierr);
2248266e20e9SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2249266e20e9SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,work,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2250266e20e9SStefano Zampini     /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,work,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
2251266e20e9SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2252266e20e9SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,work,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
22533425bc38SStefano Zampini     ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
22543425bc38SStefano Zampini   }
22553425bc38SStefano Zampini   /* BDDC rhs */
22563425bc38SStefano Zampini   ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr);
22578eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
22583425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
22593425bc38SStefano Zampini   }
22603425bc38SStefano Zampini   /* apply BDDC */
2261229984c5Sstefano_zampini   ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
2262dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
2263266e20e9SStefano Zampini   ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
2264229984c5Sstefano_zampini 
22653425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
22663425bc38SStefano Zampini   ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr);
22673425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
22683425bc38SStefano Zampini   ierr = VecScatterEnd(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2269229984c5Sstefano_zampini   /* Add contribution to interface pressures */
2270229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
2271229984c5Sstefano_zampini     ierr = MatMult(mat_ctx->B_BB,pcis->vec1_B,mat_ctx->vP);CHKERRQ(ierr);
2272229984c5Sstefano_zampini     if (pcbddc->switch_static) {
2273229984c5Sstefano_zampini       ierr = MatMultAdd(mat_ctx->B_BI,pcis->vec1_D,mat_ctx->vP,mat_ctx->vP);CHKERRQ(ierr);
2274229984c5Sstefano_zampini     }
2275229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2276229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->l2g_p,mat_ctx->vP,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2277229984c5Sstefano_zampini   }
22783425bc38SStefano Zampini   PetscFunctionReturn(0);
22793425bc38SStefano Zampini }
22801e6b0712SBarry Smith 
22813425bc38SStefano Zampini /*@
22820f202f7eSStefano Zampini  PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side
22833425bc38SStefano Zampini 
22843425bc38SStefano Zampini    Collective
22853425bc38SStefano Zampini 
22863425bc38SStefano Zampini    Input Parameters:
22870f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix object obtained by a call to PCBDDCCreateFETIDPOperators
22880f202f7eSStefano Zampini -  standard_rhs    - the right-hand side of the original linear system
22893425bc38SStefano Zampini 
22903425bc38SStefano Zampini    Output Parameters:
22910f202f7eSStefano Zampini .  fetidp_flux_rhs - the right-hand side for the FETI-DP linear system
22923425bc38SStefano Zampini 
22933425bc38SStefano Zampini    Level: developer
22943425bc38SStefano Zampini 
22953425bc38SStefano Zampini    Notes:
22963425bc38SStefano Zampini 
22970f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetSolution
22983425bc38SStefano Zampini @*/
22993425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
23003425bc38SStefano Zampini {
2301674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
23023425bc38SStefano Zampini   PetscErrorCode ierr;
23033425bc38SStefano Zampini 
23043425bc38SStefano Zampini   PetscFunctionBegin;
2305266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1);
2306266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_rhs,VEC_CLASSID,2);
2307266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_rhs,VEC_CLASSID,3);
23083425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
2309163d334eSBarry Smith   ierr = PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr);
23103425bc38SStefano Zampini   PetscFunctionReturn(0);
23113425bc38SStefano Zampini }
23121e6b0712SBarry Smith 
23133425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
23143425bc38SStefano Zampini {
2315674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
23163425bc38SStefano Zampini   PC_IS*         pcis;
23173425bc38SStefano Zampini   PC_BDDC*       pcbddc;
23183425bc38SStefano Zampini   PetscErrorCode ierr;
2319229984c5Sstefano_zampini   Vec            work;
23203425bc38SStefano Zampini 
23213425bc38SStefano Zampini   PetscFunctionBegin;
23223425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
23233425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
23243425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
23253425bc38SStefano Zampini 
23263425bc38SStefano Zampini   /* apply B_delta^T */
2327af140850Sstefano_zampini   ierr = VecSet(pcis->vec1_B,0.);CHKERRQ(ierr);
23283425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
23293425bc38SStefano Zampini   ierr = VecScatterEnd(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
23303425bc38SStefano Zampini   ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
2331229984c5Sstefano_zampini   if (mat_ctx->l2g_p) {
2332229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2333229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->l2g_p,fetidp_flux_sol,mat_ctx->vP,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2334229984c5Sstefano_zampini     ierr = MatMultAdd(mat_ctx->Bt_BB,mat_ctx->vP,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
2335229984c5Sstefano_zampini   }
2336229984c5Sstefano_zampini 
23373425bc38SStefano Zampini   /* compute rhs for BDDC application */
23383425bc38SStefano Zampini   ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr);
23398eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
23403425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
2341229984c5Sstefano_zampini     if (mat_ctx->l2g_p) {
2342229984c5Sstefano_zampini       ierr = VecScale(mat_ctx->vP,-1.);CHKERRQ(ierr);
2343229984c5Sstefano_zampini       ierr = MatMultAdd(mat_ctx->Bt_BI,mat_ctx->vP,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr);
23443425bc38SStefano Zampini     }
2345229984c5Sstefano_zampini   }
2346229984c5Sstefano_zampini 
23473425bc38SStefano Zampini   /* apply BDDC */
2348229984c5Sstefano_zampini   ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
2349dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
2350229984c5Sstefano_zampini 
2351229984c5Sstefano_zampini   /* put values into global vector */
2352af140850Sstefano_zampini   if (pcbddc->ChangeOfBasisMatrix) work = pcbddc->work_change;
2353af140850Sstefano_zampini   else work = standard_sol;
2354229984c5Sstefano_zampini   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2355229984c5Sstefano_zampini   ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
23568eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
23573425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
23583425bc38SStefano Zampini     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr);
235900f6b531SStefano Zampini     ierr = VecAYPX(pcis->vec1_D,-1.0,mat_ctx->temp_solution_D);CHKERRQ(ierr);
236000f6b531SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr);
23613425bc38SStefano Zampini   }
2362229984c5Sstefano_zampini 
2363229984c5Sstefano_zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2364229984c5Sstefano_zampini   ierr = VecScatterEnd(pcis->global_to_D,pcis->vec1_D,work,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2365266e20e9SStefano Zampini   /* add p0 solution to final solution */
2366229984c5Sstefano_zampini   ierr = PCBDDCBenignGetOrSetP0(mat_ctx->pc,work,PETSC_FALSE);CHKERRQ(ierr);
2367fc17d649SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2368af140850Sstefano_zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,work,standard_sol);CHKERRQ(ierr);
2369fc17d649SStefano Zampini   }
2370af140850Sstefano_zampini   ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr);
2371af140850Sstefano_zampini   if (mat_ctx->g2g_p) {
2372229984c5Sstefano_zampini     ierr = VecScatterBegin(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2373229984c5Sstefano_zampini     ierr = VecScatterEnd(mat_ctx->g2g_p,fetidp_flux_sol,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2374229984c5Sstefano_zampini   }
23753425bc38SStefano Zampini   PetscFunctionReturn(0);
23763425bc38SStefano Zampini }
23771e6b0712SBarry Smith 
23783425bc38SStefano Zampini /*@
23790f202f7eSStefano Zampini  PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system
23803425bc38SStefano Zampini 
23813425bc38SStefano Zampini    Collective
23823425bc38SStefano Zampini 
23833425bc38SStefano Zampini    Input Parameters:
23840f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators
23850f202f7eSStefano Zampini -  fetidp_flux_sol - the solution of the FETI-DP linear system
23863425bc38SStefano Zampini 
23873425bc38SStefano Zampini    Output Parameters:
23880f202f7eSStefano Zampini .  standard_sol    - the solution defined on the physical domain
23893425bc38SStefano Zampini 
23903425bc38SStefano Zampini    Level: developer
23913425bc38SStefano Zampini 
23923425bc38SStefano Zampini    Notes:
23933425bc38SStefano Zampini 
23940f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetRHS
23953425bc38SStefano Zampini @*/
23963425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
23973425bc38SStefano Zampini {
2398674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
23993425bc38SStefano Zampini   PetscErrorCode ierr;
24003425bc38SStefano Zampini 
24013425bc38SStefano Zampini   PetscFunctionBegin;
2402266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_mat,MAT_CLASSID,1);
2403266e20e9SStefano Zampini   PetscValidHeaderSpecific(fetidp_flux_sol,VEC_CLASSID,2);
2404266e20e9SStefano Zampini   PetscValidHeaderSpecific(standard_sol,VEC_CLASSID,3);
24053425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
2406163d334eSBarry Smith   ierr = PetscUseMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr);
24073425bc38SStefano Zampini   PetscFunctionReturn(0);
24083425bc38SStefano Zampini }
24091e6b0712SBarry Smith 
2410547c9a8eSstefano_zampini static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, PetscBool fully_redundant, const char* prefix, Mat *fetidp_mat, PC *fetidp_pc)
24113425bc38SStefano Zampini {
2412674ae819SStefano Zampini 
2413674ae819SStefano Zampini   FETIDPMat_ctx  fetidpmat_ctx;
24143425bc38SStefano Zampini   Mat            newmat;
2415674ae819SStefano Zampini   FETIDPPC_ctx   fetidppc_ctx;
24163425bc38SStefano Zampini   PC             newpc;
2417ce94432eSBarry Smith   MPI_Comm       comm;
24183425bc38SStefano Zampini   PetscErrorCode ierr;
24193425bc38SStefano Zampini 
24203425bc38SStefano Zampini   PetscFunctionBegin;
2421ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
24223425bc38SStefano Zampini   /* FETIDP linear matrix */
24233425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr);
24241720468bSStefano Zampini   fetidpmat_ctx->fully_redundant = fully_redundant;
24253425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr);
2426a5bb87b3Sstefano_zampini   ierr = MatCreateShell(comm,fetidpmat_ctx->n,fetidpmat_ctx->n,fetidpmat_ctx->N,fetidpmat_ctx->N,fetidpmat_ctx,&newmat);CHKERRQ(ierr);
24273425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr);
2428edf7251bSStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT_TRANSPOSE,(void (*)(void))FETIDPMatMultTranspose);CHKERRQ(ierr);
24293425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr);
2430547c9a8eSstefano_zampini   ierr = MatSetOptionsPrefix(newmat,prefix);CHKERRQ(ierr);
2431547c9a8eSstefano_zampini   ierr = MatAppendOptionsPrefix(newmat,"fetidp_");CHKERRQ(ierr);
24323425bc38SStefano Zampini   ierr = MatSetUp(newmat);CHKERRQ(ierr);
24333425bc38SStefano Zampini   /* FETIDP preconditioner */
24343425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr);
24353425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr);
24363425bc38SStefano Zampini   ierr = PCCreate(comm,&newpc);CHKERRQ(ierr);
2437e1214c54Sstefano_zampini   ierr = PCSetOperators(newpc,newmat,newmat);CHKERRQ(ierr);
2438e1214c54Sstefano_zampini   ierr = PCSetOptionsPrefix(newpc,prefix);CHKERRQ(ierr);
2439e1214c54Sstefano_zampini   ierr = PCAppendOptionsPrefix(newpc,"fetidp_");CHKERRQ(ierr);
2440e1214c54Sstefano_zampini   if (!fetidpmat_ctx->l2g_lambda_only) {
24413425bc38SStefano Zampini     ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
24423425bc38SStefano Zampini     ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr);
24433425bc38SStefano Zampini     ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr);
2444edf7251bSStefano Zampini     ierr = PCShellSetApplyTranspose(newpc,FETIDPPCApplyTranspose);CHKERRQ(ierr);
2445c45b8d2dSstefano_zampini     ierr = PCShellSetView(newpc,FETIDPPCView);CHKERRQ(ierr);
24463425bc38SStefano Zampini     ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
2447e1214c54Sstefano_zampini   } else {
2448e1214c54Sstefano_zampini     KSP      *ksps;
2449e1214c54Sstefano_zampini     PC       lagpc;
2450e1214c54Sstefano_zampini     Mat      M,AM,PM;
2451e1214c54Sstefano_zampini     PetscInt nn;
2452e1214c54Sstefano_zampini 
2453e1214c54Sstefano_zampini     ierr = PetscObjectQuery((PetscObject)pc,"__KSPFETIDP_PPmat",(PetscObject*)&M);CHKERRQ(ierr);
2454e1214c54Sstefano_zampini     ierr = PCSetType(newpc,PCFIELDSPLIT);CHKERRQ(ierr);
2455e1214c54Sstefano_zampini     ierr = PCFieldSplitSetIS(newpc,"lag",fetidpmat_ctx->lagrange);CHKERRQ(ierr);
2456e1214c54Sstefano_zampini     ierr = PCFieldSplitSetIS(newpc,"p",fetidpmat_ctx->pressure);CHKERRQ(ierr);
2457e1214c54Sstefano_zampini     ierr = PCFieldSplitSetType(newpc,PC_COMPOSITE_SCHUR);CHKERRQ(ierr);
245840c75d76SStefano Zampini     ierr = PCFieldSplitSetSchurFactType(newpc,PC_FIELDSPLIT_SCHUR_FACT_DIAG);CHKERRQ(ierr);
2459e1214c54Sstefano_zampini     ierr = PCFieldSplitSetSchurPre(newpc,PC_FIELDSPLIT_SCHUR_PRE_USER,M);CHKERRQ(ierr);
2460c096484dSStefano Zampini     ierr = PCFieldSplitSetSchurScale(newpc,1.0);CHKERRQ(ierr);
2461e1214c54Sstefano_zampini     ierr = PCSetFromOptions(newpc);CHKERRQ(ierr);
2462e1214c54Sstefano_zampini     ierr = PCSetUp(newpc);CHKERRQ(ierr);
2463e1214c54Sstefano_zampini 
2464e1214c54Sstefano_zampini     /* set the solver for the (0,0) block */
246540c75d76SStefano Zampini     ierr = PCFieldSplitGetSubKSP(newpc,&nn,&ksps);CHKERRQ(ierr);
2466e1214c54Sstefano_zampini     ierr = PCCreate(comm,&lagpc);CHKERRQ(ierr);
2467e1214c54Sstefano_zampini     ierr = PCSetType(lagpc,PCSHELL);CHKERRQ(ierr);
2468e1214c54Sstefano_zampini     ierr = KSPGetOperators(ksps[0],&AM,&PM);CHKERRQ(ierr);
2469e1214c54Sstefano_zampini     ierr = PCSetOperators(lagpc,AM,PM);CHKERRQ(ierr);
2470e1214c54Sstefano_zampini     ierr = PCShellSetContext(lagpc,fetidppc_ctx);CHKERRQ(ierr);
2471e1214c54Sstefano_zampini     ierr = PCShellSetApply(lagpc,FETIDPPCApply);CHKERRQ(ierr);
2472e1214c54Sstefano_zampini     ierr = PCShellSetApplyTranspose(lagpc,FETIDPPCApplyTranspose);CHKERRQ(ierr);
2473e1214c54Sstefano_zampini     ierr = PCShellSetView(lagpc,FETIDPPCView);CHKERRQ(ierr);
2474e1214c54Sstefano_zampini     ierr = PCShellSetDestroy(lagpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
2475e1214c54Sstefano_zampini     ierr = KSPSetPC(ksps[0],lagpc);CHKERRQ(ierr);
2476e1214c54Sstefano_zampini     ierr = PCDestroy(&lagpc);CHKERRQ(ierr);
2477e1214c54Sstefano_zampini     ierr = PetscFree(ksps);CHKERRQ(ierr);
2478e1214c54Sstefano_zampini   }
24793425bc38SStefano Zampini   /* return pointers for objects created */
24803425bc38SStefano Zampini   *fetidp_mat = newmat;
24813425bc38SStefano Zampini   *fetidp_pc = newpc;
24823425bc38SStefano Zampini   PetscFunctionReturn(0);
24833425bc38SStefano Zampini }
24841e6b0712SBarry Smith 
248594ef8ddeSSatish Balay /*@C
24860f202f7eSStefano Zampini  PCBDDCCreateFETIDPOperators - Create FETI-DP operators
24873425bc38SStefano Zampini 
24883425bc38SStefano Zampini    Collective
24893425bc38SStefano Zampini 
24903425bc38SStefano Zampini    Input Parameters:
24911720468bSStefano Zampini +  pc - the BDDC preconditioning context (setup should have been called before)
2492547c9a8eSstefano_zampini .  fully_redundant - true for a fully redundant set of Lagrange multipliers
2493547c9a8eSstefano_zampini -  prefix - optional options database prefix for the objects to be created (can be NULL)
249428509bceSStefano Zampini 
249528509bceSStefano Zampini    Output Parameters:
24960f202f7eSStefano Zampini +  fetidp_mat - shell FETI-DP matrix object
24970f202f7eSStefano Zampini -  fetidp_pc  - shell Dirichlet preconditioner for FETI-DP matrix
249828509bceSStefano Zampini 
24993425bc38SStefano Zampini    Level: developer
25003425bc38SStefano Zampini 
25013425bc38SStefano Zampini    Notes:
25020f202f7eSStefano Zampini      Currently the only operations provided for FETI-DP matrix are MatMult and MatMultTranspose
25033425bc38SStefano Zampini 
25040f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCMatFETIDPGetRHS, PCBDDCMatFETIDPGetSolution
25053425bc38SStefano Zampini @*/
2506547c9a8eSstefano_zampini PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, PetscBool fully_redundant, const char *prefix, Mat *fetidp_mat, PC *fetidp_pc)
25073425bc38SStefano Zampini {
25083425bc38SStefano Zampini   PetscErrorCode ierr;
25093425bc38SStefano Zampini 
25103425bc38SStefano Zampini   PetscFunctionBegin;
25113425bc38SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
25123425bc38SStefano Zampini   if (pc->setupcalled) {
2513547c9a8eSstefano_zampini     ierr = PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,PetscBool,const char*,Mat*,PC*),(pc,fully_redundant,prefix,fetidp_mat,fetidp_pc));CHKERRQ(ierr);
25144247aa23Sstefano_zampini   } else SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"You must call PCSetup_BDDC() first \n");
25153425bc38SStefano Zampini   PetscFunctionReturn(0);
25163425bc38SStefano Zampini }
25170c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
2518da1bb401SStefano Zampini /*MC
2519da1bb401SStefano Zampini    PCBDDC - Balancing Domain Decomposition by Constraints.
25200c7d97c5SJed Brown 
252128509bceSStefano Zampini    An implementation of the BDDC preconditioner based on
252228509bceSStefano Zampini 
252328509bceSStefano Zampini .vb
252428509bceSStefano Zampini    [1] C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
252528509bceSStefano 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
252628509bceSStefano Zampini    [3] J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", http://arxiv.org/abs/0712.3977
25270f202f7eSStefano 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
252828509bceSStefano Zampini .ve
252928509bceSStefano Zampini 
253028509bceSStefano Zampini    The matrix to be preconditioned (Pmat) must be of type MATIS.
253128509bceSStefano Zampini 
25320f202f7eSStefano Zampini    Currently works with MATIS matrices with local matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers.
253328509bceSStefano Zampini 
253428509bceSStefano Zampini    It also works with unsymmetric and indefinite problems.
253528509bceSStefano Zampini 
2536b6fdb6dfSStefano 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.
2537b6fdb6dfSStefano Zampini 
2538c7017625SStefano 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).
253928509bceSStefano Zampini 
25400f202f7eSStefano 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()
254130368db7SStefano Zampini    Additional information on dofs can be provided by using PCBDDCSetDofsSplitting(), PCBDDCSetDirichletBoundaries(), PCBDDCSetNeumannBoundaries(), and PCBDDCSetPrimalVerticesIS() and their local counterparts.
254228509bceSStefano Zampini 
25430f202f7eSStefano Zampini    Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). Non-singular modes are retained via SVD.
254428509bceSStefano Zampini 
25450f202f7eSStefano 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.
25460f202f7eSStefano Zampini    User defined change of basis can be passed to PCBDDC by using PCBDDCSetChangeOfBasisMat()
254728509bceSStefano Zampini 
25480f202f7eSStefano Zampini    The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using a MatPartitioning object.
254928509bceSStefano Zampini 
2550df4d28bfSStefano 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.
255128509bceSStefano Zampini 
25520f202f7eSStefano 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.
25530f202f7eSStefano Zampini    Deluxe scaling is not supported yet for FETI-DP.
25540f202f7eSStefano Zampini 
25550f202f7eSStefano Zampini    Options Database Keys (some of them, run with -h for a complete list):
25560f202f7eSStefano Zampini 
25570f202f7eSStefano Zampini .    -pc_bddc_use_vertices <true> - use or not vertices in primal space
25580f202f7eSStefano Zampini .    -pc_bddc_use_edges <true> - use or not edges in primal space
25590f202f7eSStefano Zampini .    -pc_bddc_use_faces <false> - use or not faces in primal space
25600f202f7eSStefano Zampini .    -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems
25610f202f7eSStefano Zampini .    -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only)
25620f202f7eSStefano Zampini .    -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested
25630f202f7eSStefano Zampini .    -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1])
256428509bceSStefano Zampini .    -pc_bddc_levels <0> - maximum number of levels for multilevel
25650f202f7eSStefano 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)
25665459c157SBarry 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)
25670f202f7eSStefano Zampini .    -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling
25680f202f7eSStefano 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)
2569bd2a564bSStefano 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)
257028509bceSStefano Zampini -    -pc_bddc_check_level <0> - set verbosity level of debugging output
257128509bceSStefano Zampini 
257228509bceSStefano Zampini    Options for Dirichlet, Neumann or coarse solver can be set with
257328509bceSStefano Zampini .vb
257428509bceSStefano Zampini       -pc_bddc_dirichlet_
257528509bceSStefano Zampini       -pc_bddc_neumann_
257628509bceSStefano Zampini       -pc_bddc_coarse_
257728509bceSStefano Zampini .ve
25780f202f7eSStefano Zampini    e.g -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. PCBDDC uses by default KPSPREONLY and PCLU.
257928509bceSStefano Zampini 
25800f202f7eSStefano Zampini    When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified as
258128509bceSStefano Zampini .vb
2582312be037SStefano Zampini       -pc_bddc_dirichlet_lN_
2583312be037SStefano Zampini       -pc_bddc_neumann_lN_
2584312be037SStefano Zampini       -pc_bddc_coarse_lN_
258528509bceSStefano Zampini .ve
25860f202f7eSStefano Zampini    Note that level number ranges from the finest (0) to the coarsest (N).
25870f202f7eSStefano 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.
25880f202f7eSStefano Zampini .vb
25890f202f7eSStefano Zampini      -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3
25900f202f7eSStefano Zampini .ve
25910f202f7eSStefano 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
2592da1bb401SStefano Zampini 
2593da1bb401SStefano Zampini    Level: intermediate
2594da1bb401SStefano Zampini 
2595e94cfbe0SPatrick Sanan    Developer Notes:
2596da1bb401SStefano Zampini 
2597da1bb401SStefano Zampini    Contributed by Stefano Zampini
2598da1bb401SStefano Zampini 
2599da1bb401SStefano Zampini .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
2600da1bb401SStefano Zampini M*/
2601b2573a8aSBarry Smith 
26028cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
2603da1bb401SStefano Zampini {
2604da1bb401SStefano Zampini   PetscErrorCode      ierr;
2605da1bb401SStefano Zampini   PC_BDDC             *pcbddc;
2606da1bb401SStefano Zampini 
2607da1bb401SStefano Zampini   PetscFunctionBegin;
2608b00a9115SJed Brown   ierr     = PetscNewLog(pc,&pcbddc);CHKERRQ(ierr);
2609da1bb401SStefano Zampini   pc->data = (void*)pcbddc;
2610da1bb401SStefano Zampini 
2611da1bb401SStefano Zampini   /* create PCIS data structure */
2612da1bb401SStefano Zampini   ierr = PCISCreate(pc);CHKERRQ(ierr);
2613da1bb401SStefano Zampini 
26149326c5c6Sstefano_zampini   /* create local graph structure */
26159326c5c6Sstefano_zampini   ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr);
26169326c5c6Sstefano_zampini 
26179326c5c6Sstefano_zampini   /* BDDC nonzero defaults */
261808a5cf49SStefano Zampini   pcbddc->use_local_adj             = PETSC_TRUE;
261947d04d0dSStefano Zampini   pcbddc->use_vertices              = PETSC_TRUE;
262047d04d0dSStefano Zampini   pcbddc->use_edges                 = PETSC_TRUE;
26213301b35fSStefano Zampini   pcbddc->symmetric_primal          = PETSC_TRUE;
262214f95afaSStefano Zampini   pcbddc->vertex_size               = 1;
2623c703fcc7SStefano Zampini   pcbddc->recompute_topography      = PETSC_TRUE;
262468457ee5SStefano Zampini   pcbddc->coarse_size               = -1;
262585c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = PETSC_TRUE;
262647d04d0dSStefano Zampini   pcbddc->coarsening_ratio          = 8;
262757de7509SStefano Zampini   pcbddc->coarse_eqs_per_proc       = 1;
262827b6a85dSStefano Zampini   pcbddc->benign_compute_correction = PETSC_TRUE;
26291e0482f5SStefano Zampini   pcbddc->nedfield                  = -1;
26301e0482f5SStefano Zampini   pcbddc->nedglobal                 = PETSC_TRUE;
2631be12c134Sstefano_zampini   pcbddc->graphmaxcount             = PETSC_MAX_INT;
2632b96c3477SStefano Zampini   pcbddc->sub_schurs_layers         = -1;
2633bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[0]     = 0.0;
2634bd2a564bSStefano Zampini   pcbddc->adaptive_threshold[1]     = 0.0;
2635b7eb3628SStefano Zampini 
2636da1bb401SStefano Zampini   /* function pointers */
2637da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
263893bd9ae7SStefano Zampini   pc->ops->applytranspose      = PCApplyTranspose_BDDC;
2639da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
2640da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
2641da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
26426b78500eSPatrick Sanan   pc->ops->view                = PCView_BDDC;
2643da1bb401SStefano Zampini   pc->ops->applyrichardson     = 0;
2644da1bb401SStefano Zampini   pc->ops->applysymmetricleft  = 0;
2645da1bb401SStefano Zampini   pc->ops->applysymmetricright = 0;
2646534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
2647534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
26489326c5c6Sstefano_zampini   pc->ops->reset               = PCReset_BDDC;
2649da1bb401SStefano Zampini 
2650da1bb401SStefano Zampini   /* composing function */
2651a13144ffSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDiscreteGradient_C",PCBDDCSetDiscreteGradient_BDDC);CHKERRQ(ierr);
2652a198735bSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDivergenceMat_C",PCBDDCSetDivergenceMat_BDDC);CHKERRQ(ierr);
2653906d46d4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",PCBDDCSetChangeOfBasisMat_BDDC);CHKERRQ(ierr);
2654674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
265530368db7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",PCBDDCSetPrimalVerticesIS_BDDC);CHKERRQ(ierr);
2656bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr);
26572b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC);CHKERRQ(ierr);
2658b8ffe317SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC);CHKERRQ(ierr);
26592b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC);CHKERRQ(ierr);
2660bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
266182ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",PCBDDCSetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
2662bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
266382ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",PCBDDCSetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
2664bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
266582ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",PCBDDCGetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
2666bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
266782ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",PCBDDCGetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
2668bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
266963602bcaSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",PCBDDCSetDofsSplittingLocal_BDDC);CHKERRQ(ierr);
2670bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
2671bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr);
2672bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr);
2673bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr);
2674a06fd7f2SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCPreSolveChangeRHS_C",PCPreSolveChangeRHS_BDDC);CHKERRQ(ierr);
2675ab8c8b98SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",PCSetCoordinates_BDDC);CHKERRQ(ierr);
2676da1bb401SStefano Zampini   PetscFunctionReturn(0);
2677da1bb401SStefano Zampini }
2678